Ver código fonte

build up the references hierarchy

Julius Pfrommer 10 anos atrás
pai
commit
ccf5a58e4e

+ 1 - 1
Makefile.am

@@ -1,5 +1,5 @@
 #AM_CFLAGS  = -std=c99 -pedantic -pipe -fPIC -fno-exceptions -fstack-protector -Wl,-z,relro -Wl,-z,now -fvisibility=hidden -W -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar -Wformat-nonliteral -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -Werror
-AM_CFLAGS  = -std=c99 -pedantic -pipe -fPIC -funsigned-char -Wno-pointer-sign -fno-exceptions -fstack-protector -fvisibility=hidden -W -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar -Wformat-nonliteral -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -Werror
+AM_CFLAGS  = -std=c99 -pedantic -pipe -fPIC -fno-exceptions -fstack-protector -fvisibility=hidden -W -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar -Wformat-nonliteral -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -Werror
 AM_LDFLAGS =
 AM_LDADD =
 

+ 1 - 1
examples/src/opcuaServer.c

@@ -23,7 +23,7 @@ UA_Int32 serverCallback(void * arg) {
 	UA_Node const * node;
 	UA_ExpandedNodeId serverStatusNodeId = NS0EXPANDEDNODEID(2256);
 	retval = Namespace_get(ns0, &(serverStatusNodeId.nodeId),&node, UA_NULL);
-	if(retval != UA_SUCCESS || node == UA_NULL){
+	if(retval == UA_SUCCESS){
 		((UA_ServerStatusDataType*)(((UA_VariableNode*)node)->value.data))->currentTime = UA_DateTime_now();
 	}
 

+ 385 - 91
src/ua_application.c

@@ -1,5 +1,6 @@
 #include "ua_application.h"
 #include "ua_namespace.h"
+#include "ua_services_internal.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -22,7 +23,6 @@ UA_Node* create_node_ns0(UA_Int32 class, UA_Int32 nodeClass, UA_Int32 const id,
 	return n;
 }
 
-#define C2UA_STRING(s) (UA_String) { sizeof(s)-1, (UA_Byte*) s }
 void appMockup_init() {
 	// create namespaces
 	// TODO: A table that maps the namespaceUris to Ids
@@ -37,21 +37,350 @@ void appMockup_init() {
 	UA_indexedList_addValueToFront(appMockup.namespaces,0,ns0);
 	UA_indexedList_addValueToFront(appMockup.namespaces,1,local);
 
-    /***************/
-    /* Namespace 0 */
-    /***************/
+    /**************/
+    /* References */
+    /**************/
 
-    // ReferenceTypes
+    // ReferenceType Ids
+	UA_NodeId RefTypeId_References = NS0NODEID(31);
+	UA_NodeId RefTypeId_NonHierarchicalReferences = NS0NODEID(32);
+	UA_NodeId RefTypeId_HierarchicalReferences = NS0NODEID(33);
+	UA_NodeId RefTypeId_HasChild = NS0NODEID(34);
 	UA_NodeId RefTypeId_Organizes = NS0NODEID(35);
-	/* UA_NodeId RefTypeId_HasEventSource = NS0NODEID(36); */
-	/* UA_NodeId RefTypeId_HasModellingRule = NS0NODEID(37); */
-	/* UA_NodeId RefTypeId_HasEncoding = NS0NODEID(38); */
-	/* UA_NodeId RefTypeId_HasDescription = NS0NODEID(39); */
+	UA_NodeId RefTypeId_HasEventSource = NS0NODEID(36);
+	UA_NodeId RefTypeId_HasModellingRule = NS0NODEID(37);
+	UA_NodeId RefTypeId_HasEncoding = NS0NODEID(38);
+	UA_NodeId RefTypeId_HasDescription = NS0NODEID(39);
 	UA_NodeId RefTypeId_HasTypeDefinition = NS0NODEID(40);
-	/* UA_NodeId RefTypeId_HasSubtype = NS0NODEID(45); */
+	UA_NodeId RefTypeId_GeneratesEvent = NS0NODEID(41);
+	UA_NodeId RefTypeId_Aggregates = NS0NODEID(44);
+	UA_NodeId RefTypeId_HasSubtype = NS0NODEID(45);
 	UA_NodeId RefTypeId_HasProperty = NS0NODEID(46);
 	UA_NodeId RefTypeId_HasComponent = NS0NODEID(47);
-	/* UA_NodeId RefTypeId_HasNotifier = NS0NODEID(48); */
+	UA_NodeId RefTypeId_HasNotifier = NS0NODEID(48);
+	UA_NodeId RefTypeId_HasOrderedComponent = NS0NODEID(49);
+	UA_NodeId RefTypeId_HasModelParent = NS0NODEID(50);
+	UA_NodeId RefTypeId_FromState = NS0NODEID(51);
+	UA_NodeId RefTypeId_ToState = NS0NODEID(52);
+	UA_NodeId RefTypeId_HasCause = NS0NODEID(53);
+	UA_NodeId RefTypeId_HasEffect = NS0NODEID(54);
+	UA_NodeId RefTypeId_HasHistoricalConfiguration = NS0NODEID(56);
+
+	UA_ReferenceTypeNode *references;
+	UA_ReferenceTypeNode_new(&references);
+	references->nodeId = RefTypeId_References;
+	references->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	references->browseName = UA_QUALIFIEDNAME_STATIC("References");
+	references->displayName = UA_LOCALIZEDTEXT_STATIC("References");
+	references->description = UA_LOCALIZEDTEXT_STATIC("References");
+	references->isAbstract = UA_TRUE;
+	references->symmetric = UA_TRUE;
+	Namespace_insert(ns0,(UA_Node*)references);
+
+	UA_ReferenceTypeNode *hierarchicalreferences;
+	UA_ReferenceTypeNode_new(&hierarchicalreferences);
+	hierarchicalreferences->nodeId = RefTypeId_HierarchicalReferences;
+	hierarchicalreferences->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hierarchicalreferences->browseName = UA_QUALIFIEDNAME_STATIC("HierarchicalReferences");
+	hierarchicalreferences->displayName = UA_LOCALIZEDTEXT_STATIC("HierarchicalReferences");
+	hierarchicalreferences->description = UA_LOCALIZEDTEXT_STATIC("HierarchicalReferences");
+	hierarchicalreferences->isAbstract = UA_TRUE;
+	hierarchicalreferences->symmetric = UA_FALSE;
+	AddReference((UA_Node*)hierarchicalreferences, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_References, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hierarchicalreferences);
+
+	UA_ReferenceTypeNode *nonhierarchicalreferences;
+	UA_ReferenceTypeNode_new(&nonhierarchicalreferences);
+	nonhierarchicalreferences->nodeId = RefTypeId_NonHierarchicalReferences;
+	nonhierarchicalreferences->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	nonhierarchicalreferences->browseName = UA_QUALIFIEDNAME_STATIC("NonHierarchicalReferences");
+	nonhierarchicalreferences->displayName = UA_LOCALIZEDTEXT_STATIC("NonHierarchicalReferences");
+	nonhierarchicalreferences->description = UA_LOCALIZEDTEXT_STATIC("NonHierarchicalReferences");
+	nonhierarchicalreferences->isAbstract = UA_TRUE;
+	nonhierarchicalreferences->symmetric = UA_FALSE;
+	AddReference((UA_Node*)nonhierarchicalreferences, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_References, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)nonhierarchicalreferences);
+
+	UA_ReferenceTypeNode *haschild;
+	UA_ReferenceTypeNode_new(&haschild);
+	haschild->nodeId = RefTypeId_HasChild;
+	haschild->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	haschild->browseName = UA_QUALIFIEDNAME_STATIC("HasChild");
+	haschild->displayName = UA_LOCALIZEDTEXT_STATIC("HasChild");
+	haschild->description = UA_LOCALIZEDTEXT_STATIC("HasChild");
+	haschild->isAbstract = UA_TRUE;
+	haschild->symmetric = UA_FALSE;
+	AddReference((UA_Node*)haschild, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_HierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)haschild);
+
+	UA_ReferenceTypeNode *organizes;
+	UA_ReferenceTypeNode_new(&organizes);
+	organizes->nodeId = RefTypeId_Organizes;
+	organizes->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	organizes->browseName = UA_QUALIFIEDNAME_STATIC("Organizes");
+	organizes->displayName = UA_LOCALIZEDTEXT_STATIC("Organizes");
+	organizes->description = UA_LOCALIZEDTEXT_STATIC("Organizes");
+	organizes->isAbstract = UA_FALSE;
+	organizes->symmetric = UA_FALSE;
+	organizes->inverseName = UA_LOCALIZEDTEXT_STATIC("OrganizedBy");
+	AddReference((UA_Node*)organizes, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_HierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)organizes);
+
+	UA_ReferenceTypeNode *haseventsource;
+	UA_ReferenceTypeNode_new(&haseventsource);
+	haseventsource->nodeId = RefTypeId_HasEventSource;
+	haseventsource->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	haseventsource->browseName = UA_QUALIFIEDNAME_STATIC("HasEventSource");
+	haseventsource->displayName = UA_LOCALIZEDTEXT_STATIC("HasEventSource");
+	haseventsource->description = UA_LOCALIZEDTEXT_STATIC("HasEventSource");
+	haseventsource->isAbstract = UA_FALSE;
+	haseventsource->symmetric = UA_FALSE;
+	haseventsource->inverseName = UA_LOCALIZEDTEXT_STATIC("EventSourceOf");
+	AddReference((UA_Node*)haseventsource, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_HierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)haseventsource);
+
+	UA_ReferenceTypeNode *hasmodellingrule;
+	UA_ReferenceTypeNode_new(&hasmodellingrule);
+	hasmodellingrule->nodeId = RefTypeId_HasModellingRule;
+	hasmodellingrule->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hasmodellingrule->browseName = UA_QUALIFIEDNAME_STATIC("HasModellingRule");
+	hasmodellingrule->displayName = UA_LOCALIZEDTEXT_STATIC("HasModellingRule");
+	hasmodellingrule->description = UA_LOCALIZEDTEXT_STATIC("HasModellingRule");
+	hasmodellingrule->isAbstract = UA_FALSE;
+	hasmodellingrule->symmetric = UA_FALSE;
+	hasmodellingrule->inverseName = UA_LOCALIZEDTEXT_STATIC("ModellingRuleOf");
+	AddReference((UA_Node*)hasmodellingrule, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hasmodellingrule);
+
+	UA_ReferenceTypeNode *hasencoding;
+	UA_ReferenceTypeNode_new(&hasencoding);
+	hasencoding->nodeId = RefTypeId_HasEncoding;
+	hasencoding->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hasencoding->browseName = UA_QUALIFIEDNAME_STATIC("HasEncoding");
+	hasencoding->displayName = UA_LOCALIZEDTEXT_STATIC("HasEncoding");
+	hasencoding->description = UA_LOCALIZEDTEXT_STATIC("HasEncoding");
+	hasencoding->isAbstract = UA_FALSE;
+	hasencoding->symmetric = UA_FALSE;
+	hasencoding->inverseName = UA_LOCALIZEDTEXT_STATIC("EncodingOf");
+	AddReference((UA_Node*)hasencoding, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hasencoding);
+
+	UA_ReferenceTypeNode *hasdescription;
+	UA_ReferenceTypeNode_new(&hasdescription);
+	hasdescription->nodeId = RefTypeId_HasDescription;
+	hasdescription->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hasdescription->browseName = UA_QUALIFIEDNAME_STATIC("HasDescription");
+	hasdescription->displayName = UA_LOCALIZEDTEXT_STATIC("HasDescription");
+	hasdescription->description = UA_LOCALIZEDTEXT_STATIC("HasDescription");
+	hasdescription->isAbstract = UA_FALSE;
+	hasdescription->symmetric = UA_FALSE;
+	hasdescription->inverseName = UA_LOCALIZEDTEXT_STATIC("DescriptionOf");
+	AddReference((UA_Node*)hasdescription, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hasdescription);
+
+	UA_ReferenceTypeNode *hastypedefinition;
+	UA_ReferenceTypeNode_new(&hastypedefinition);
+	hastypedefinition->nodeId = RefTypeId_HasTypeDefinition;
+	hastypedefinition->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hastypedefinition->browseName = UA_QUALIFIEDNAME_STATIC("HasTypeDefinition");
+	hastypedefinition->displayName = UA_LOCALIZEDTEXT_STATIC("HasTypeDefinition");
+	hastypedefinition->description = UA_LOCALIZEDTEXT_STATIC("HasTypeDefinition");
+	hastypedefinition->isAbstract = UA_FALSE;
+	hastypedefinition->symmetric = UA_FALSE;
+	hastypedefinition->inverseName = UA_LOCALIZEDTEXT_STATIC("TypeDefinitionOf");
+	AddReference((UA_Node*)hastypedefinition, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hastypedefinition);
+
+	UA_ReferenceTypeNode *generatesevent;
+	UA_ReferenceTypeNode_new(&generatesevent);
+	generatesevent->nodeId = RefTypeId_GeneratesEvent;
+	generatesevent->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	generatesevent->browseName = UA_QUALIFIEDNAME_STATIC("GeneratesEvent");
+	generatesevent->displayName = UA_LOCALIZEDTEXT_STATIC("GeneratesEvent");
+	generatesevent->description = UA_LOCALIZEDTEXT_STATIC("GeneratesEvent");
+	generatesevent->isAbstract = UA_FALSE;
+	generatesevent->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("GeneratedBy");
+	AddReference((UA_Node*)generatesevent, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)generatesevent);
+
+	UA_ReferenceTypeNode *aggregates;
+	UA_ReferenceTypeNode_new(&aggregates);
+	aggregates->nodeId = RefTypeId_Aggregates;
+	aggregates->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	aggregates->browseName = UA_QUALIFIEDNAME_STATIC("Aggregates");
+	aggregates->displayName = UA_LOCALIZEDTEXT_STATIC("Aggregates");
+	aggregates->description = UA_LOCALIZEDTEXT_STATIC("Aggregates");
+	aggregates->isAbstract = UA_TRUE;
+	aggregates->symmetric = UA_FALSE;
+	AddReference((UA_Node*)aggregates, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_HierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)aggregates);
+	
+	UA_ReferenceTypeNode *hassubtype;
+	UA_ReferenceTypeNode_new(&hassubtype);
+	hassubtype->nodeId = RefTypeId_HasSubtype;
+	hassubtype->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hassubtype->browseName = UA_QUALIFIEDNAME_STATIC("HasSubtype");
+	hassubtype->displayName = UA_LOCALIZEDTEXT_STATIC("HasSubtype");
+	hassubtype->description = UA_LOCALIZEDTEXT_STATIC("HasSubtype");
+	hassubtype->isAbstract = UA_FALSE;
+	hassubtype->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("SubtypeOf");
+	AddReference((UA_Node*)hassubtype, &(UA_ReferenceNode){RefTypeId_HasSubtype, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_HasChild, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hassubtype);
+
+	UA_ReferenceTypeNode *hasproperty;
+	UA_ReferenceTypeNode_new(&hasproperty);
+	hasproperty->nodeId = RefTypeId_HasProperty;
+	hasproperty->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hasproperty->browseName = UA_QUALIFIEDNAME_STATIC("HasProperty");
+	hasproperty->displayName = UA_LOCALIZEDTEXT_STATIC("HasProperty");
+	hasproperty->description = UA_LOCALIZEDTEXT_STATIC("HasProperty");
+	hasproperty->isAbstract = UA_FALSE;
+	hasproperty->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("PropertyOf");
+	AddReference((UA_Node*)hasproperty, &(UA_ReferenceNode){RefTypeId_HasProperty, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_Aggregates, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hasproperty);
+
+	UA_ReferenceTypeNode *hascomponent;
+	UA_ReferenceTypeNode_new(&hascomponent);
+	hascomponent->nodeId = RefTypeId_HasComponent;
+	hascomponent->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hascomponent->browseName = UA_QUALIFIEDNAME_STATIC("HasComponent");
+	hascomponent->displayName = UA_LOCALIZEDTEXT_STATIC("HasComponent");
+	hascomponent->description = UA_LOCALIZEDTEXT_STATIC("HasComponent");
+	hascomponent->isAbstract = UA_FALSE;
+	hascomponent->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("ComponentOf");
+	AddReference((UA_Node*)hascomponent, &(UA_ReferenceNode){RefTypeId_HasComponent, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_Aggregates, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hascomponent);
+
+	UA_ReferenceTypeNode *hasnotifier;
+	UA_ReferenceTypeNode_new(&hasnotifier);
+	hasnotifier->nodeId = RefTypeId_HasNotifier;
+	hasnotifier->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hasnotifier->browseName = UA_QUALIFIEDNAME_STATIC("HasNotifier");
+	hasnotifier->displayName = UA_LOCALIZEDTEXT_STATIC("HasNotifier");
+	hasnotifier->description = UA_LOCALIZEDTEXT_STATIC("HasNotifier");
+	hasnotifier->isAbstract = UA_FALSE;
+	hasnotifier->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("NotifierOf");
+	AddReference((UA_Node*)hasnotifier, &(UA_ReferenceNode){RefTypeId_HasNotifier, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_HasEventSource, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hasnotifier);
+
+	UA_ReferenceTypeNode *hasorderedcomponent;
+	UA_ReferenceTypeNode_new(&hasorderedcomponent);
+	hasorderedcomponent->nodeId = RefTypeId_HasOrderedComponent;
+	hasorderedcomponent->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hasorderedcomponent->browseName = UA_QUALIFIEDNAME_STATIC("HasOrderedComponent");
+	hasorderedcomponent->displayName = UA_LOCALIZEDTEXT_STATIC("HasOrderedComponent");
+	hasorderedcomponent->description = UA_LOCALIZEDTEXT_STATIC("HasOrderedComponent");
+	hasorderedcomponent->isAbstract = UA_FALSE;
+	hasorderedcomponent->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("OrderedComponentOf");
+	AddReference((UA_Node*)hasorderedcomponent, &(UA_ReferenceNode){RefTypeId_HasOrderedComponent, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_HasComponent, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hasorderedcomponent);
+
+	UA_ReferenceTypeNode *hasmodelparent;
+	UA_ReferenceTypeNode_new(&hasmodelparent);
+	hasmodelparent->nodeId = RefTypeId_HasModelParent;
+	hasmodelparent->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hasmodelparent->browseName = UA_QUALIFIEDNAME_STATIC("HasModelParent");
+	hasmodelparent->displayName = UA_LOCALIZEDTEXT_STATIC("HasModelParent");
+	hasmodelparent->description = UA_LOCALIZEDTEXT_STATIC("HasModelParent");
+	hasmodelparent->isAbstract = UA_FALSE;
+	hasmodelparent->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("ModelParentOf");
+	AddReference((UA_Node*)hasmodelparent, &(UA_ReferenceNode){RefTypeId_HasModelParent, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hasmodelparent);
+
+	UA_ReferenceTypeNode *fromstate;
+	UA_ReferenceTypeNode_new(&fromstate);
+	fromstate->nodeId = RefTypeId_FromState;
+	fromstate->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	fromstate->browseName = UA_QUALIFIEDNAME_STATIC("FromState");
+	fromstate->displayName = UA_LOCALIZEDTEXT_STATIC("FromState");
+	fromstate->description = UA_LOCALIZEDTEXT_STATIC("FromState");
+	fromstate->isAbstract = UA_FALSE;
+	fromstate->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("ToTransition");
+	AddReference((UA_Node*)fromstate, &(UA_ReferenceNode){RefTypeId_FromState, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)fromstate);
+
+	UA_ReferenceTypeNode *tostate;
+	UA_ReferenceTypeNode_new(&tostate);
+	tostate->nodeId = RefTypeId_ToState;
+	tostate->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	tostate->browseName = UA_QUALIFIEDNAME_STATIC("ToState");
+	tostate->displayName = UA_LOCALIZEDTEXT_STATIC("ToState");
+	tostate->description = UA_LOCALIZEDTEXT_STATIC("ToState");
+	tostate->isAbstract = UA_FALSE;
+	tostate->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("FromTransition");
+	AddReference((UA_Node*)tostate, &(UA_ReferenceNode){RefTypeId_ToState, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)tostate);
+
+	UA_ReferenceTypeNode *hascause;
+	UA_ReferenceTypeNode_new(&hascause);
+	hascause->nodeId = RefTypeId_HasCause;
+	hascause->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hascause->browseName = UA_QUALIFIEDNAME_STATIC("HasCause");
+	hascause->displayName = UA_LOCALIZEDTEXT_STATIC("HasCause");
+	hascause->description = UA_LOCALIZEDTEXT_STATIC("HasCause");
+	hascause->isAbstract = UA_FALSE;
+	hascause->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("MayBeCausedBy");
+	AddReference((UA_Node*)hascause, &(UA_ReferenceNode){RefTypeId_HasCause, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hascause);
+
+	UA_ReferenceTypeNode *haseffect;
+	UA_ReferenceTypeNode_new(&haseffect);
+	haseffect->nodeId = RefTypeId_HasEffect;
+	haseffect->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	haseffect->browseName = UA_QUALIFIEDNAME_STATIC("HasEffect");
+	haseffect->displayName = UA_LOCALIZEDTEXT_STATIC("HasEffect");
+	haseffect->description = UA_LOCALIZEDTEXT_STATIC("HasEffect");
+	haseffect->isAbstract = UA_FALSE;
+	haseffect->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("MayBeEffectedBy");
+	AddReference((UA_Node*)haseffect, &(UA_ReferenceNode){RefTypeId_HasEffect, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_NonHierarchicalReferences, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)haseffect);
+
+	UA_ReferenceTypeNode *hashistoricalconfiguration;
+	UA_ReferenceTypeNode_new(&hashistoricalconfiguration);
+	hashistoricalconfiguration->nodeId = RefTypeId_HasHistoricalConfiguration;
+	hashistoricalconfiguration->nodeClass = UA_NODECLASS_REFERENCETYPE;
+	hashistoricalconfiguration->browseName = UA_QUALIFIEDNAME_STATIC("HasHistoricalConfiguration");
+	hashistoricalconfiguration->displayName = UA_LOCALIZEDTEXT_STATIC("HasHistoricalConfiguration");
+	hashistoricalconfiguration->description = UA_LOCALIZEDTEXT_STATIC("HasHistoricalConfiguration");
+	hashistoricalconfiguration->isAbstract = UA_FALSE;
+	hashistoricalconfiguration->symmetric = UA_FALSE;
+	generatesevent->inverseName = UA_LOCALIZEDTEXT_STATIC("HistoricalConfigurationOf");
+	AddReference((UA_Node*)hashistoricalconfiguration, &(UA_ReferenceNode){RefTypeId_HasHistoricalConfiguration, UA_TRUE,
+				(UA_ExpandedNodeId){RefTypeId_Aggregates, UA_STRING_NULL, 0}}, ns0);
+	Namespace_insert(ns0,(UA_Node*)hashistoricalconfiguration);
+
 
     // ObjectTypes (Ids only)
 	UA_ExpandedNodeId ObjTypeId_FolderType = NS0EXPANDEDNODEID(61);
@@ -67,18 +396,14 @@ void appMockup_init() {
 	UA_ExpandedNodeId ObjId_ServerCapabilities = NS0EXPANDEDNODEID(2268);
 	UA_ExpandedNodeId ObjId_State = NS0EXPANDEDNODEID(2259);
 
-
 	// FolderType
 	UA_ObjectNode *folderType;
 	UA_ObjectNode_new(&folderType);
 	folderType->nodeId = NS0NODEID(61);
 	folderType->nodeClass = UA_NODECLASS_OBJECT; // I should not have to set this manually
-	folderType->browseName = (UA_QualifiedName){0, {10, "FolderType"}};
-	folderType->displayName = (UA_LocalizedText){{2,"EN"},{10, "FolderType"}};
-	folderType->description = (UA_LocalizedText){{2,"EN"},{10, "FolderType"}};
-	folderType->referencesSize = 0;
-	folderType->references = UA_NULL;
-
+	folderType->browseName = UA_QUALIFIEDNAME_STATIC("FolderType");
+	folderType->displayName = UA_LOCALIZEDTEXT_STATIC("FolderType");
+	folderType->description = UA_LOCALIZEDTEXT_STATIC("FolderType");
 	Namespace_insert(ns0,(UA_Node*)folderType);
 
 	// Root
@@ -86,18 +411,14 @@ void appMockup_init() {
 	UA_ObjectNode_new(&root);
 	root->nodeId = NS0NODEID(84);
 	root->nodeClass = UA_NODECLASS_OBJECT; // I should not have to set this manually
-	root->browseName = (UA_QualifiedName){0, {4, "Root"}};
-	root->displayName = (UA_LocalizedText){{2,"EN"},{4, "Root"}};
-	root->description = (UA_LocalizedText){{2,"EN"},{4, "Root"}};
-	root->referencesSize = 4;
-	UA_alloc((void**) &root->references, sizeof(UA_ReferenceNode)*4);
-	UA_ReferenceNode *static_nodes = (UA_ReferenceNode[4]){
-		{RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType},
-		{RefTypeId_Organizes, UA_FALSE, ObjId_ObjectsFolder},
-		{RefTypeId_Organizes, UA_FALSE, ObjId_TypesFolder},
-		{RefTypeId_Organizes, UA_FALSE, ObjId_ViewsFolder}};
-	UA_memcpy(root->references, static_nodes, sizeof(UA_ReferenceNode)*4);
-
+	root->browseName = UA_QUALIFIEDNAME_STATIC("Root");
+	root->displayName = UA_LOCALIZEDTEXT_STATIC("Root");
+	root->description = UA_LOCALIZEDTEXT_STATIC("Root");
+	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType}, ns0);
+	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjTypeId_FolderType}, ns0);
+	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_ObjectsFolder}, ns0);
+	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_TypesFolder}, ns0);
+	AddReference((UA_Node*)root, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_ViewsFolder}, ns0);
 	Namespace_insert(ns0,(UA_Node*)root);
 	
 	// Objects
@@ -105,14 +426,11 @@ void appMockup_init() {
 	UA_ObjectNode_new(&objects);
 	objects->nodeId = ObjId_ObjectsFolder.nodeId;
 	objects->nodeClass = UA_NODECLASS_OBJECT;
-	objects->browseName = (UA_QualifiedName){0, {7, "Objects"}};
-	objects->displayName = (UA_LocalizedText){{2,"EN"},{7, "Objects"}};
-	objects->description = (UA_LocalizedText){{2,"EN"},{7, "Objects"}};
-	objects->referencesSize = 2;
-	objects->references = (UA_ReferenceNode[2]){
-		{RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType},
-		{RefTypeId_Organizes, UA_FALSE, ObjId_Server}};
-
+	objects->browseName = UA_QUALIFIEDNAME_STATIC("Objects");
+	objects->displayName = UA_LOCALIZEDTEXT_STATIC("Objects");
+	objects->description = UA_LOCALIZEDTEXT_STATIC("Objects");
+	AddReference((UA_Node*)objects, &(UA_ReferenceNode){RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType}, ns0);
+	AddReference((UA_Node*)objects, &(UA_ReferenceNode){RefTypeId_Organizes, UA_FALSE, ObjId_Server}, ns0);
 	Namespace_insert(ns0,(UA_Node*)objects);
 
 	// Views
@@ -120,13 +438,10 @@ void appMockup_init() {
 	UA_ObjectNode_new(&views);
 	views->nodeId = ObjId_ViewsFolder.nodeId;
 	views->nodeClass = UA_NODECLASS_OBJECT;
-	views->browseName = (UA_QualifiedName){0, {5, "Views"}};
-	views->displayName = (UA_LocalizedText){{2,"EN"},{5, "Views"}};
-	views->description = (UA_LocalizedText){{2,"EN"},{5, "Views"}};
-	views->referencesSize = 1;
-	views->references = (UA_ReferenceNode[1]){
-		{RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType}};
-
+	views->browseName = UA_QUALIFIEDNAME_STATIC("Views");
+	views->displayName = UA_LOCALIZEDTEXT_STATIC("Views");
+	views->description = UA_LOCALIZEDTEXT_STATIC("Views");
+	AddReference((UA_Node*)views, &(UA_ReferenceNode){RefTypeId_HasTypeDefinition, UA_FALSE, ObjTypeId_FolderType}, ns0);
 	Namespace_insert(ns0,(UA_Node*)views);
 
 	// Server
@@ -134,16 +449,13 @@ void appMockup_init() {
 	UA_ObjectNode_new(&server);
 	server->nodeId = ObjId_Server.nodeId;
 	server->nodeClass = UA_NODECLASS_OBJECT;
-	server->browseName = (UA_QualifiedName){0, {6, "Server"}};
-	server->displayName = (UA_LocalizedText){{2,"EN"},{6, "Server"}};
-	server->description = (UA_LocalizedText){{2,"EN"},{6, "Server"}};
-	server->referencesSize = 0;
-	server->references = (UA_ReferenceNode[4]){
-		{RefTypeId_HasComponent, UA_FALSE, ObjId_ServerCapabilities},
-		{RefTypeId_HasComponent, UA_FALSE, ObjId_NamespaceArray},
-		{RefTypeId_HasProperty, UA_FALSE, ObjId_ServerStatus},
-		{RefTypeId_HasProperty, UA_FALSE, ObjId_ServerArray}};
-
+	server->browseName = UA_QUALIFIEDNAME_STATIC("Server");
+	server->displayName = UA_LOCALIZEDTEXT_STATIC("Server");
+	server->description = UA_LOCALIZEDTEXT_STATIC("Server");
+	AddReference((UA_Node*)server, &(UA_ReferenceNode){RefTypeId_HasComponent, UA_FALSE, ObjId_ServerCapabilities}, ns0);
+	AddReference((UA_Node*)server, &(UA_ReferenceNode){RefTypeId_HasComponent, UA_FALSE, ObjId_NamespaceArray}, ns0);
+	AddReference((UA_Node*)server, &(UA_ReferenceNode){RefTypeId_HasProperty, UA_FALSE, ObjId_ServerStatus}, ns0);
+	AddReference((UA_Node*)server, &(UA_ReferenceNode){RefTypeId_HasProperty, UA_FALSE, ObjId_ServerArray}, ns0);
 	Namespace_insert(ns0,(UA_Node*)server);
 
 	// NamespaceArray
@@ -151,23 +463,21 @@ void appMockup_init() {
 	UA_VariableNode_new(&namespaceArray);
 	namespaceArray->nodeId = ObjId_NamespaceArray.nodeId;
 	namespaceArray->nodeClass = UA_NODECLASS_VARIABLE; //FIXME: this should go into _new?
-	namespaceArray->browseName = (UA_QualifiedName){0, {13, "NamespaceArray"}};
-	namespaceArray->displayName = (UA_LocalizedText){{2,"EN"},{13, "NamespaceArray"}};
-	namespaceArray->description = (UA_LocalizedText){{2,"EN"},{13, "NamespaceArray"}};
-	//FIXME: can we avoid new here?
+	namespaceArray->browseName = UA_QUALIFIEDNAME_STATIC("NamespaceArray");
+	namespaceArray->displayName = UA_LOCALIZEDTEXT_STATIC("NamespaceArray");
+	namespaceArray->description = UA_LOCALIZEDTEXT_STATIC("NamespaceArray");
 	UA_Array_new((void**)&namespaceArray->value.data, 2, &UA_.types[UA_STRING]);
 	namespaceArray->value.vt = &UA_.types[UA_STRING];
 	namespaceArray->value.arrayLength = 2;
 	UA_String_copycstring("http://opcfoundation.org/UA/",&((UA_String *)((namespaceArray->value).data))[0]);
 	UA_String_copycstring("http://localhost:16664/open62541/",&((UA_String *)(((namespaceArray)->value).data))[1]);
 	namespaceArray->arrayDimensionsSize = 1;
-	UA_Int32 dimensions = 2;
+	UA_UInt32 dimensions = 2;
 	namespaceArray->arrayDimensions = &dimensions;
 	namespaceArray->dataType = NS0NODEID(UA_STRING_NS0);
 	namespaceArray->valueRank = 1;
 	namespaceArray->minimumSamplingInterval = 1.0;
 	namespaceArray->historizing = UA_FALSE;
-
 	Namespace_insert(ns0,(UA_Node*)namespaceArray);
 
 	// ServerStatus
@@ -175,40 +485,39 @@ void appMockup_init() {
 	UA_VariableNode_new(&serverstatus);
 	serverstatus->nodeId = ObjId_ServerStatus.nodeId;
 	serverstatus->nodeClass = UA_NODECLASS_VARIABLE;
-	serverstatus->browseName = (UA_QualifiedName){0, {12, "ServerStatus"}};
-	serverstatus->displayName = (UA_LocalizedText){{2,"EN"},{12, "ServerStatus"}};
-	serverstatus->description = (UA_LocalizedText){{2,"EN"},{12, "ServerStatus"}};
+	serverstatus->browseName = UA_QUALIFIEDNAME_STATIC("ServerStatus");
+	serverstatus->displayName = UA_LOCALIZEDTEXT_STATIC("ServerStatus");
+	serverstatus->description = UA_LOCALIZEDTEXT_STATIC("ServerStatus");
 	UA_ServerStatusDataType *status;
 	UA_ServerStatusDataType_new(&status);
 	status->startTime = UA_DateTime_now();
 	status->currentTime = UA_DateTime_now();
 	status->state = UA_SERVERSTATE_RUNNING;
-	status->buildInfo = (UA_BuildInfo){{13,"open62541.org"}, {9,"open62541"}, {9,"open62541"},
-									  {3, "0.0"}, {3, "0.0"}, UA_DateTime_now()};
+	status->buildInfo = (UA_BuildInfo){
+		.productUri = UA_STRING_STATIC("open62541.org"),
+		.manufacturerName = UA_STRING_STATIC("open62541"),
+		.productName = UA_STRING_STATIC("open62541"),
+		.softwareVersion = UA_STRING_STATIC("0.0"),
+		.buildNumber = UA_STRING_STATIC("0.0"),
+		.buildDate = UA_DateTime_now()};
 	status->secondsTillShutdown = 99999999;
-	status->shutdownReason = (UA_LocalizedText){{2,"EN"},{7, "because"}};
+	status->shutdownReason = UA_LOCALIZEDTEXT_STATIC("because");
 	serverstatus->value.vt = &UA_.types[UA_SERVERSTATUSDATATYPE]; // gets encoded as an extensionobject
 	serverstatus->value.arrayLength = 1;
 	serverstatus->value.data = status;
- 
 	Namespace_insert(ns0,(UA_Node*)serverstatus);
 
-
-
 	// State (Component of ServerStatus)
 	UA_VariableNode *state;
 	UA_VariableNode_new(&state);
 	state->nodeId = ObjId_State.nodeId;
 	state->nodeClass = UA_NODECLASS_VARIABLE;
-	state->browseName = (UA_QualifiedName){0, {5, "State"}};
-	state->displayName = (UA_LocalizedText){{2,"EN"},{5, "State"}};
-	state->description = (UA_LocalizedText){{2,"EN"},{5, "State"}};
+	state->browseName = UA_QUALIFIEDNAME_STATIC("State");
+	state->displayName = UA_LOCALIZEDTEXT_STATIC("State");
+	state->description = UA_LOCALIZEDTEXT_STATIC("State");
 	state->value.vt = &UA_borrowed_.types[UA_SERVERSTATE];
 	state->value.arrayLength = 1;
 	state->value.data = &status->state; // points into the other object.
-
-	state->referencesSize = 0;
-	state->references = UA_NULL;
 	Namespace_insert(ns0,(UA_Node*)state);
 
 	//TODO: free(namespaceArray->value.data) later or forget it
@@ -227,21 +536,6 @@ void appMockup_init() {
 	/* v->historizing = UA_FALSE; */
 	/* Namespace_insert(ns0,np); */
 
-
-	/*TEST */
-	const UA_Node * foundNode1;
-	const UA_Node * foundNode2;
-	Namespace_Entry_Lock *lock1;
-
-	Namespace_get(ns0, &root->nodeId,
-			&foundNode1, &lock1);
-
-	Namespace_get(ns0, &foundNode1->references[0].targetId.nodeId,
-			&foundNode2, &lock1);
-
-	/*TEST END*/
-
-
     /*******************/
     /* Namespace local */
     /*******************/

+ 6 - 1
src/ua_services.h

@@ -109,7 +109,12 @@ UA_Int32 Service_CloseSession(SL_Channel *channel, const UA_CloseSessionRequest
  * @brief This Service is used to add one or more Nodes into the AddressSpace hierarchy.
  */
 UA_Int32 Service_AddNodes(SL_Channel *channel, const UA_AddNodesRequest *request, UA_AddNodesResponse *response);
-// Service_AddReferences
+
+/**
+ * @brief This Service is used to add one or more References to one or more Nodes
+ */
+UA_Int32 Service_AddReferences(SL_Channel *channel, const UA_AddReferencesRequest *request, UA_AddReferencesResponse *response);
+
 // Service_DeleteNodes
 // Service_DeleteReferences
 /** @} */

+ 16 - 0
src/ua_services_internal.h

@@ -0,0 +1,16 @@
+/**
+ * @brief This files contains helper functions for the UA-Services that are used
+ * internally as well (with a simplified API as no access rights are checked).
+ */
+
+#include "ua_namespace.h"
+#include "ua_types.h"
+#include "ua_types_generated.h"
+
+/* @brief Add a reference (and the inverse reference to the target node).
+ *
+ * @param The node to which the reference shall be added
+ * @param The reference itself
+ * @param The namespace where the target node is looked up for the reverse reference (this is omitted if targetns is UA_NULL)
+ */
+UA_Int32 AddReference(UA_Node *node, UA_ReferenceNode *reference, Namespace *targetns);

+ 51 - 0
src/ua_services_nodemanagement.c

@@ -1,6 +1,7 @@
 #include "ua_services.h"
 #include "ua_statuscodes.h"
 #include "ua_namespace.h"
+#include "ua_services_internal.h"
 
 #define CHECKED_ACTION(ACTION, CLEAN_UP, GOTO) do {	\
 	status |= ACTION; \
@@ -88,3 +89,53 @@ UA_Int32 Service_AddNodes(SL_Channel *channel, const UA_AddNodesRequest *request
 	return UA_SUCCESS;
 	
 }
+
+static UA_Int32 AddSingleReference(UA_Node *node, UA_ReferenceNode *reference) {
+	// TODO: Check if reference already exists
+
+	UA_Int32 count = node->referencesSize;
+	if(count < 0) count = 0;
+	UA_ReferenceNode *old_refs = node->references;
+	UA_ReferenceNode *new_refs;
+
+	UA_Int32 retval = UA_alloc((void **)&new_refs, sizeof(UA_ReferenceNode)*(count+1));
+	if(retval != UA_SUCCESS)
+		return UA_ERROR;
+	UA_memcpy(new_refs, old_refs, sizeof(UA_ReferenceNode)*count);
+	retval |= UA_ReferenceNode_copy(reference, &new_refs[count]);
+
+	if(retval != UA_SUCCESS) {
+		UA_free(new_refs);
+		return retval;
+	}
+	
+	node->references = new_refs;
+	node->referencesSize = count+1;
+	return retval;
+}
+
+UA_Int32 AddReference(UA_Node *node, UA_ReferenceNode *reference, Namespace *targetns) {
+	UA_Int32 retval = AddSingleReference(node, reference);
+	if(retval != UA_SUCCESS || targetns == UA_NULL)
+		return retval;
+
+	UA_Node *targetnode;
+	Namespace_Entry_Lock *lock;
+	// TODO: Nodes in the namespace are immutable (for lockless multithreading).
+	// Do a copy every time?
+	if(Namespace_get(targetns, &reference->targetId.nodeId, (const UA_Node**)&targetnode, &lock) != UA_SUCCESS)
+		return UA_ERROR;
+
+	UA_ReferenceNode inversereference;
+	inversereference.referenceTypeId = reference->referenceTypeId;
+	inversereference.isInverse = !reference->isInverse;
+	inversereference.targetId = (UA_ExpandedNodeId){node->nodeId, UA_STRING_NULL, 0};	
+	retval = AddSingleReference(targetnode, &inversereference);
+	Namespace_Entry_Lock_release(lock);
+
+	return retval;
+}
+
+UA_Int32 Service_AddReferences(SL_Channel *channel, const UA_AddReferencesRequest *request, UA_AddReferencesResponse *response) {
+	return UA_ERROR;
+}

+ 6 - 4
src/ua_types.h

@@ -275,13 +275,12 @@ UA_TYPE_PROTOTYPES(UA_ExtensionObject)
 UA_TYPE_PROTOTYPES(UA_DataValue)
 UA_TYPE_PROTOTYPES(UA_Variant)
 UA_TYPE_PROTOTYPES(UA_DiagnosticInfo)
-
-/* Not built-in types */
 UA_TYPE_PROTOTYPES(UA_InvalidType)
-/* UA_TYPE_PROTOTYPES (UA_NodeClass) */
-/* UA_TYPE_PROTOTYPES(UA_ReferenceDescription) */
 
 /* String */
+#define UA_STRING_NULL (UA_String){-1, UA_NULL}
+#define UA_STRING_STATIC(STRING) (UA_String){sizeof(STRING)-1, (UA_Byte*)STRING}
+
 UA_Int32 UA_String_copycstring(char const *src, UA_String *dst);
 UA_Int32 UA_String_copyprintf(char const *fmt, UA_String *dst, ...);
 UA_Int32 UA_String_equal(const UA_String *string1, const UA_String *string2);
@@ -327,9 +326,12 @@ UA_Boolean UA_NodeId_isBasicType(UA_NodeId const *id);
 UA_Boolean UA_ExpandedNodeId_isNull(const UA_ExpandedNodeId *p);
 
 /* QualifiedName */
+#define UA_QUALIFIEDNAME_STATIC(STRING) \
+	(UA_QualifiedName){0, {sizeof(STRING)-1, (UA_Byte*)STRING}}
 void UA_QualifiedName_printf(char const *label, const UA_QualifiedName *qn);
 
 /* LocalizedText */
+#define UA_LOCALIZEDTEXT_STATIC(STRING) (UA_LocalizedText){{2, (UA_Byte*)"en"}, UA_STRING_STATIC(STRING)}
 UA_Int32 UA_LocalizedText_copycstring(char const *src, UA_LocalizedText *dst);
 
 /* Variant */

+ 3 - 3
tests/check_base64.c

@@ -5,7 +5,7 @@
 START_TEST(base64_test_2padding)
 {
 	//this is base64'd ASCII string "open62541!"
-	UA_String encodedString = {16, "b3BlbjYyNTQxIQ=="};
+	UA_String encodedString = UA_STRING_STATIC("b3BlbjYyNTQxIQ==");
 
 	//assure that we allocate exactly 10 bytes
 	ck_assert_int_eq(UA_base64_getDecodedSize(&encodedString), 10);
@@ -34,7 +34,7 @@ START_TEST(base64_test_1padding)
 {
 
 	//this is base64'd ASCII string "open62541!!"
-	UA_String encodedString = {16, "b3BlbjYyNTQxISE="};
+	UA_String encodedString = UA_STRING_STATIC("b3BlbjYyNTQxISE=");
 
 	//assure that we allocate exactly 11 bytes
 	ck_assert_int_eq(UA_base64_getDecodedSize(&encodedString), 11);
@@ -64,7 +64,7 @@ START_TEST(base64_test_0padding)
 {
 
 	//this is base64'd ASCII string "open62541"
-	UA_String encodedString = {12, "b3BlbjYyNTQx"};
+	UA_String encodedString = UA_STRING_STATIC("b3BlbjYyNTQx");
 
 	//assure that we allocate exactly 9 bytes
 	ck_assert_int_eq(UA_base64_getDecodedSize(&encodedString), 9);