Ver código fonte

Merge branch 'master' into dev

Merges various features and fixes from master into dev, most notably:
* Changed access appy for creating nodes and references
* Fixes to the client library for code reusage
* Namespace generation
ichrispa 9 anos atrás
pai
commit
5fb3476f5a

+ 8 - 8
.travis.yml

@@ -33,7 +33,7 @@ script:
 - mkdir -p build
 - cd build
 - cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_DOCUMENTATION=ON -DGENERATE_SELFSIGNED=ON ..
-- make -j doc
+- make doc
 - make selfsigned
 - cp -r doc ..
 - cp server_cert.der ..
@@ -41,7 +41,7 @@ script:
 - cd .. && rm build -rf && mkdir -p build && cd build
 - echo "Cross compile release build for MinGW 32 bit"
 - cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw32.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
-- make -j
+- make 
 - cp ../README.md .
 - cp ../LICENSE .
 - cp ../AUTHORS .
@@ -52,7 +52,7 @@ script:
 - cd .. && rm build -rf && mkdir -p build && cd build
 - echo "Cross compile release build for MinGW 64 bit"
 - cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw64.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
-- make -j
+- make 
 - cp ../README.md .
 - cp ../LICENSE .
 - cp ../AUTHORS .
@@ -63,13 +63,13 @@ script:
 - cd .. && rm build -rf && mkdir -p build && cd build
 - echo "Cross compile release build for 32-bit linux"
 - cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-gcc-m32.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
-- make -j
+- make 
 - tar -pczf open62541-linux32.tar.gz ../doc ../server_cert.der ../LICENSE ../AUTHORS ../README.md server_static server client_static client libopen62541.so open62541.h open62541.c
 - cp open62541-linux32.tar.gz ..
 - cd .. && rm build -rf && mkdir -p build && cd build
 - echo "Compile release build for 64-bit linux"
 - cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_AMALGAMATION=ON -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
-- make -j
+- make 
 - tar -pczf open62541-linux64.tar.gz ../doc ../server_cert.der ../LICENSE ../AUTHORS ../README.md server_static server client_static client libopen62541.so open62541.h open62541.c
 - cp open62541-linux64.tar.gz ..
 - cp open62541.h .. #copy single file-release
@@ -83,11 +83,11 @@ script:
 - sudo update-alternatives --config gcc
 - echo "Compile multithreaded version"
 - cmake -DENABLE_MULTITHREADING=ON -DBUILD_EXAMPLESERVER=ON ..
-- make -j
+- make 
 - cd .. && rm build -rf && mkdir -p build && cd build
 - echo "Debug build and unit tests (64 bit)"
 - cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_DEMO_NODESET=ON -DBUILD_UNIT_TESTS=ON -DENABLE_COVERAGE=ON ..
-- make -j && make test
+- make && make test
 - coveralls --gcov /usr/bin/gcov-4.8 -E '.*\.h' -E '.*CMakeCXXCompilerId\.cpp' -E '.*CMakeCCompilerId\.c' -r ../
 - cd .. 
 after_success:
@@ -101,7 +101,7 @@ before_deploy:
 - cd -
 - export PATH=$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/
 - cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-rpi64.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
-- make -j
+- make 
 - tar -pczf open62541-raspberrypi.tar.gz ../doc ../server_cert.der ../LICENSE ../AUTHORS ../README.md server_static server client_static client libopen62541.so open62541.h open62541.c
 - cp open62541-raspberrypi.tar.gz ..
 - cd ..

+ 42 - 9
CMakeLists.txt

@@ -3,6 +3,17 @@ cmake_minimum_required(VERSION 2.8.8)
 
 project(open62541 C)
 
+FIND_PACKAGE(PythonInterp REQUIRED)
+
+# Find Python-lxml
+execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
+if(NOT EXISTS "${PYTHON_SITE_PACKAGES}/lxml")
+    execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(True))" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if(NOT EXISTS "${PYTHON_SITE_PACKAGES}/lxml")
+        message( FATAL_ERROR "Python-lxml is not installed.")
+    endif()
+endif()
+
 find_package(Git)
 if(GIT_FOUND)
     execute_process(COMMAND ${GIT_EXECUTABLE} describe --abbrev=7 --dirty --always --tags RESULT_VARIABLE res_var OUTPUT_VARIABLE GIT_COM_ID )
@@ -82,9 +93,9 @@ set(lib_sources ${PROJECT_SOURCE_DIR}/src/ua_types.c
                 ${PROJECT_SOURCE_DIR}/src/ua_securechannel.c
                 ${PROJECT_SOURCE_DIR}/src/ua_session.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_server.c
-				${PROJECT_SOURCE_DIR}/src/server/ua_server_addressspace.c
-				${PROJECT_SOURCE_DIR}/src/server/ua_server_binary.c
-				${PROJECT_SOURCE_DIR}/src/server/ua_nodes.c
+                ${PROJECT_SOURCE_DIR}/src/server/ua_server_addressspace.c
+                ${PROJECT_SOURCE_DIR}/src/server/ua_server_binary.c
+                ${PROJECT_SOURCE_DIR}/src/server/ua_nodes.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_server_worker.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_securechannel_manager.c
                 ${PROJECT_SOURCE_DIR}/src/server/ua_session_manager.c
@@ -124,7 +135,7 @@ else()
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
                           ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.h
                    PRE_BUILD
-                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py --typedescriptions ${PROJECT_SOURCE_DIR}/tools/schema/NodeIds.csv 0 ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_types
+                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py --typedescriptions ${PROJECT_SOURCE_DIR}/tools/schema/NodeIds.csv 0 ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_types
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_datatypes.py
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/NodeIds.csv)
@@ -133,16 +144,38 @@ endif()
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
                           ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
                    PRE_BUILD
-                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py --ns0-types-xml ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd 1 ${PROJECT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_transport
+                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py --ns0-types-xml ${PROJECT_SOURCE_DIR}/tools/schema/Opc.Ua.Types.bsd 1 ${PROJECT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd ${PROJECT_BINARY_DIR}/src_generated/ua_transport
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_datatypes.py
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd)
 
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids.h
                    PRE_BUILD
-                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/generate_nodeids.py ${PROJECT_SOURCE_DIR}/tools/schema/NodeIds.csv ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids
+                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_nodeids.py ${PROJECT_SOURCE_DIR}/tools/schema/NodeIds.csv ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_nodeids.py
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/schema/NodeIds.csv)
 
+option(ENABLE_GENERATE_NAMESPACE0 "Generate and load UA XML Namespace 0 definition" OFF)
+if(ENABLE_GENERATE_NAMESPACE0)
+add_definitions(-DENABLE_GENERATE_NAMESPACE0)
+set(GENERATE_NAMESPACE0_FILE "Opc.Ua.NodeSet2.xml" CACHE STRING "Namespace definition XML file")
+set_property(CACHE GENERATE_NAMESPACE0_FILE PROPERTY STRINGS Opc.Ua.NodeSet2.xml Opc.Ua.NodeSet2.Minimal.xml)
+add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespaceinit_generated.c
+                          ${PROJECT_BINARY_DIR}/src_generated/ua_namespaceinit_generated.h
+                   PRE_BUILD
+                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/generate_open62541CCode.py -i ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/NodeID_AssumeExternal.txt -s description -b ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/NodeID_Blacklist.txt ${PROJECT_SOURCE_DIR}/tools/schema/namespace0/${GENERATE_NAMESPACE0_FILE} ${PROJECT_BINARY_DIR}/src_generated/ua_namespaceinit_generated
+                   DEPENDS ${PROJECT_SOURCE_DIR}/tools/schema/namespace0/${GENERATE_NAMESPACE0_FILE}
+                           ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/generate_open62541CCode.py  
+                           ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/logger.py  
+                           ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/open62541_MacroHelper.py  
+                           ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/ua_builtin_types.py  
+                           ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/ua_constants.py  
+                           ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/ua_namespace.py  
+                           ${PROJECT_SOURCE_DIR}/tools/pyUANamespace/ua_node_types.py)
+
+list(APPEND internal_headers ${PROJECT_BINARY_DIR}/src_generated/ua_namespaceinit_generated.h)
+list(APPEND lib_sources ${PROJECT_BINARY_DIR}/src_generated/ua_namespaceinit_generated.c)
+endif()
+
 ## logging
 set(UA_LOGLEVEL 300 CACHE STRING "Level at which logs shall be reported")
 
@@ -183,7 +216,7 @@ endif()
 option(ENABLE_AMALGAMATION "Concatenate the library to a single file open62541.h/.c" OFF)
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/open62541.h
                PRE_BUILD
-               COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py ${GIT_COMMIT_ID} ${CMAKE_CURRENT_BINARY_DIR}/open62541.h ${exported_headers}
+               COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py ${GIT_COMMIT_ID} ${CMAKE_CURRENT_BINARY_DIR}/open62541.h ${exported_headers}
 
 
                DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py ${exported_headers} ${internal_headers})
@@ -191,7 +224,7 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/open62541.h
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/open62541.c
                PRE_BUILD
 
-               COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py ${GIT_COMMIT_ID} ${CMAKE_CURRENT_BINARY_DIR}/open62541.c
+               COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py ${GIT_COMMIT_ID} ${CMAKE_CURRENT_BINARY_DIR}/open62541.c
                               ${PROJECT_BINARY_DIR}/src_generated/ua_config.h ${internal_headers} ${PROJECT_SOURCE_DIR}/src/server/ua_nodestore_hash.inc ${lib_sources}
 
                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})
@@ -263,7 +296,7 @@ if(GENERATE_SELFSIGNED)
     find_package(OpenSSL REQUIRED)
     add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/server_cert.der
                               ${PROJECT_BINARY_DIR}/ca.crt
-                   COMMAND python ${PROJECT_SOURCE_DIR}/tools/certs/create_self-signed.py ${PROJECT_BINARY_DIR}
+                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/certs/create_self-signed.py ${PROJECT_BINARY_DIR}
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/certs/create_self-signed.py
                            ${CMAKE_CURRENT_SOURCE_DIR}/tools/certs/localhost.cnf)
     add_custom_target(selfsigned ALL DEPENDS ${PROJECT_BINARY_DIR}/server_cert.der ${PROJECT_BINARY_DIR}/ca.crt)

+ 1 - 1
examples/server_simple.c

@@ -31,7 +31,7 @@ static void stopHandler(int sign) {
 static UA_ByteString loadCertificate(void) {
     UA_ByteString certificate = UA_STRING_NULL;
 	FILE *fp = NULL;
-	//FIXME: a potiential bug of locating the certificate, we need to get the path from the server's config
+	//FIXME: a potential bug of locating the certificate, we need to get the path from the server's config
 	fp=fopen("server_cert.der", "rb");
 
 	if(!fp) {

+ 1 - 1
include/ua_config.h.in

@@ -1,7 +1,7 @@
 #ifndef UA_CONFIG_H_
 #define UA_CONFIG_H_
 
-/* Buid options and configuration (set by cmake) */
+/* Build options and configuration (set by cmake) */
 
 #define UA_LOGLEVEL ${UA_LOGLEVEL}
 #cmakedefine UA_MULTITHREADING

+ 9 - 6
include/ua_server.h

@@ -65,7 +65,7 @@ UA_Logger UA_EXPORT UA_Server_getLogger(UA_Server *server);
  *
  * @param nThreads The number of worker threads. Is ignored if MULTITHREADING is not activated.
  *
- * @param running Points to a booloean value on the heap. When running is set to false, the worker
+ * @param running Points to a boolean value on the heap. When running is set to false, the worker
  * threads and the main loop close and the server is shut down.
  *
  * @return Indicates whether the server shut down cleanly
@@ -149,7 +149,11 @@ UA_Server_addDataSourceVariableNode(UA_Server *server, UA_DataSource dataSource,
                                     const UA_QualifiedName browseName, UA_NodeId nodeId,
                                     const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId);
 
-/** Jobs describe work that is ececuted once or repeatedly. */
+UA_StatusCode UA_EXPORT
+UA_Server_AddMonodirectionalReference(UA_Server *server, UA_NodeId sourceNodeId, UA_ExpandedNodeId targetNodeId, 
+                                      UA_NodeId referenceTypeId, UA_Boolean isforward);
+
+/** Jobs describe work that is executed once or repeatedly. */
 typedef struct {
     enum {
         UA_JOBTYPE_NOTHING,
@@ -184,7 +188,7 @@ typedef struct {
  * @param jobId Set to the guid of the repeated job. This can be used to cancel the job later on. If
  *        the pointer is null, the guid is not set.
  *
- * @return Upon sucess, UA_STATUSCODE_GOOD is returned. An error code otherwise.
+ * @return Upon success, UA_STATUSCODE_GOOD is returned. An error code otherwise.
  */
 UA_StatusCode UA_EXPORT UA_Server_addRepeatedJob(UA_Server *server, UA_Job job, UA_UInt32 interval,
                                                  UA_Guid *jobId);
@@ -227,8 +231,7 @@ typedef struct {
      *
      * @param timeout The timeout during which an event must arrive in microseconds
      
-     * @return The size of the jobs array. If the result is negative, an error has
-     * occured.
+     * @return The size of the jobs array. If the result is negative, an error has occurred.
      */
     UA_Int32 (*getJobs)(void *nlhandle, UA_Job **jobs, UA_UInt16 timeout);
 
@@ -239,7 +242,7 @@ typedef struct {
      * @param jobs When the returned integer is positive, jobs points to an array of UA_Job of the
      * returned size.
      *
-     * @return The size of the jobs array. If the result is negative, an error has occured.
+     * @return The size of the jobs array. If the result is negative, an error has occurred.
      */
     UA_Int32 (*stop)(void *nlhandle, UA_Job **jobs);
 

+ 3 - 3
include/ua_statuscodes.h

@@ -77,7 +77,7 @@ enum UA_StatusCode {
 	UA_STATUSCODE_BADSTRUCTUREMISSING = 0x80460000, // A mandatory structured parameter was missing or null.
 	UA_STATUSCODE_BADEVENTFILTERINVALID = 0x80470000, // The event filter is not valid.
 	UA_STATUSCODE_BADCONTENTFILTERINVALID = 0x80480000, // The content filter is not valid.
-	UA_STATUSCODE_BADFILTEROPERATORINVALID = 0x80c10000, // An unregognized operator was provided in a filter.
+	UA_STATUSCODE_BADFILTEROPERATORINVALID = 0x80c10000, // An unrecognized operator was provided in a filter.
 	UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED = 0x80c20000, // A valid operator was provided, but the server does not provide support for this filter operator.
 	UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH = 0x80c30000, // The number of operands provided for the filter operator was less then expected for the operand provided.
 	UA_STATUSCODE_BADFILTEROPERANDINVALID = 0x80490000, // The operand used in a content filter is not valid.
@@ -100,7 +100,7 @@ enum UA_StatusCode {
 	UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID = 0x80580000, // The signature generated with the client certificate is missing or invalid.
 	UA_STATUSCODE_BADNOVALIDCERTIFICATES = 0x80590000, // The client did not provide at least one software certificate that is valid and meets the profile requirements for the server.
 	UA_STATUSCODE_BADIDENTITYCHANGENOTSUPPORTED = 0x80c60000, // The Server does not support changing the user identity assigned to the session.
-	UA_STATUSCODE_BADREQUESTCANCELLEDBYREQUEST = 0x805a0000, // The request was cancelled by the client with the Cancel service.
+	UA_STATUSCODE_BADREQUESTCANCELLEDBYREQUEST = 0x805a0000, // The request was canceled by the client with the Cancel service.
 	UA_STATUSCODE_BADPARENTNODEIDINVALID = 0x805b0000, // The parent node id does not to refer to a valid node.
 	UA_STATUSCODE_BADREFERENCENOTALLOWED = 0x805c0000, // The reference could not be created because it violates constraints imposed by the data model.
 	UA_STATUSCODE_BADNODEIDREJECTED = 0x805d0000, // The requested node id was reject because it was either invalid or server does not allow node ids to be specified by the client.
@@ -201,7 +201,7 @@ enum UA_StatusCode {
 	UA_STATUSCODE_BADAGGREGATENOTSUPPORTED = 0x80d50000, // The requested Aggregate is not support by the server.
 	UA_STATUSCODE_BADAGGREGATEINVALIDINPUTS = 0x80d60000, // The aggregate value could not be derived due to invalid data inputs.
 	UA_STATUSCODE_BADAGGREGATECONFIGURATIONREJECTED = 0x80da0000, // The aggregate configuration is not valid for specified node.
-	UA_STATUSCODE_GOODDATAIGNORED = 0x00d90000, // The request pecifies fields which are not valid for the EventType or cannot be saved by the historian.
+	UA_STATUSCODE_GOODDATAIGNORED = 0x00d90000, // The request specifies fields which are not valid for the EventType or cannot be saved by the historian.
 	UA_STATUSCODE_GOODCOMMUNICATIONEVENT = 0x00a70000, // The communication layer has raised an event.
 	UA_STATUSCODE_GOODSHUTDOWNEVENT = 0x00a80000, // The system is shutting down.
 	UA_STATUSCODE_GOODCALLAGAIN = 0x00a90000, // The operation is not finished and needs to be called again.

+ 1 - 1
include/ua_types.h

@@ -604,7 +604,7 @@ void UA_EXPORT * UA_Array_new(const UA_DataType *dataType, UA_Int32 noElements);
 /**
  * Allocates and copies an array. dst is set to (void*)0 if not enough memory is available.
  *
- * @param src The memory location of the souce array
+ * @param src The memory location of the source array
  * @param dst The memory location where the pointer to the destination array is written
  * @param dataType The datatype of the array members
  * @param noElements The size of the array

+ 11 - 3
src/client/ua_client.c

@@ -33,7 +33,7 @@ const UA_EXPORT UA_ClientConfig UA_ClientConfig_standard =
        .maxMessageSize = 65536, .maxChunkCount = 1}};
 
 UA_Client * UA_Client_new(UA_ClientConfig config, UA_Logger logger) {
-    UA_Client *client = UA_malloc(sizeof(UA_Client));
+    UA_Client *client = UA_calloc(1, sizeof(UA_Client));
     if(!client)
         return UA_NULL;
 
@@ -222,12 +222,19 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
 
 /** If the request fails, then the response is cast to UA_ResponseHeader (at the beginning of every
     response) and filled with the appropriate error code */
-static void synchronousRequest(UA_Client *client, const void *request, const UA_DataType *requestType,
+static void synchronousRequest(UA_Client *client, void *request, const UA_DataType *requestType,
                                void *response, const UA_DataType *responseType) {
     /* Check if sc needs to be renewed */
     if(client->scExpiresAt - UA_DateTime_now() <= client->config.timeToRenewSecureChannel * 10000 )
         UA_Client_renewSecureChannel(client);
 
+    /* Copy authenticationToken token to request header */
+    typedef struct {
+        UA_RequestHeader requestHeader;
+    } headerOnlyRequest;
+    /* The cast is valid, since all requests start with a requestHeader */
+    UA_NodeId_copy(&client->authenticationToken, &((headerOnlyRequest*)request)->requestHeader.authenticationToken);
+
     if(!response)
         return;
     UA_init(response, responseType);
@@ -473,6 +480,7 @@ UA_StatusCode UA_Client_connect(UA_Client *client, UA_ConnectClientConnection co
         retval = SessionHandshake(client);
     if(retval == UA_STATUSCODE_GOOD)
         retval = ActivateSession(client);
+        
     return retval;
 }
 
@@ -587,4 +595,4 @@ void UA_Client_addMonitoredItem(UA_Client *client) {}
 void UA_Client_publish(UA_Client *client) {}
 void UA_Client_removeMonitoredItem(UA_Client *client) {}
 void UA_Client_deleteSubscription(UA_Client *client) {}
-#endif
+#endif

+ 11 - 1
src/server/ua_server.c

@@ -6,6 +6,10 @@
 #include "ua_services.h"
 #include "ua_nodeids.h"
 
+#ifdef ENABLE_GENERATE_NAMESPACE0
+#include "ua_namespaceinit_generated.h"
+#endif
+
 const UA_EXPORT UA_ServerConfig UA_ServerConfig_standard = {
     .Login_enableAnonymous = UA_TRUE,
     .Login_enableUsernamePassword = UA_TRUE,
@@ -472,7 +476,7 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
     /**************/
     /* References */
     /**************/
-    
+#ifndef ENABLE_GENERATE_NAMESPACE0
     /* Bootstrap by manually inserting "references" and "hassubtype" */
     UA_ReferenceTypeNode *references = UA_ReferenceTypeNode_new();
     copyNames((UA_Node*)references, "References");
@@ -808,6 +812,12 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
                                UA_NS0ID_BASEVARIABLETYPE, UA_FALSE);
    addVariableTypeNode_subtype(server, "PropertyType", UA_NS0ID_PROPERTYTYPE,
                                UA_NS0ID_BASEVARIABLETYPE, UA_FALSE);
+#endif
+
+#ifdef ENABLE_GENERATE_NAMESPACE0
+   //load the generated namespace
+   ua_namespaceinit_generated(server);
+#endif
 
    /*********************/
    /* The Server Object */

+ 37 - 1
src/server/ua_server_addressspace.c

@@ -78,8 +78,44 @@ UA_Server_addDataSourceVariableNode(UA_Server *server, UA_DataSource dataSource,
     return res.statusCode;
 }
 
+/* Userspace Version of addOneWayReferenceWithSession*/
+UA_StatusCode
+UA_Server_AddMonodirectionalReference(UA_Server *server, UA_NodeId sourceNodeId, UA_ExpandedNodeId targetNodeId, UA_NodeId referenceTypeId, UA_Boolean isforward) {
+    UA_AddReferencesItem ref;
+    UA_StatusCode retval = UA_STATUSCODE_GOOD;
+    
+    if (server == UA_NULL) {
+        retval |= UA_STATUSCODE_BADSERVERINDEXINVALID;
+        return retval;
+    }
+    
+    UA_AddReferencesItem_init(&ref);
+
+    retval |= UA_NodeId_copy((const UA_NodeId *) &sourceNodeId, &ref.sourceNodeId);
+    retval |= UA_ExpandedNodeId_copy((const UA_ExpandedNodeId *) &targetNodeId, &ref.targetNodeId);
+    retval |= UA_NodeId_copy((const UA_NodeId *) &referenceTypeId, &ref.referenceTypeId);
+    
+    if (isforward == UA_TRUE)
+        ref.isForward = UA_TRUE;
+    
+    const UA_Node *target = UA_NodeStore_get(server->nodestore, (const UA_NodeId*) &ref.targetNodeId);
+    if(target == UA_NULL)
+        retval |= UA_STATUSCODE_BADNODEIDINVALID;
+    else {
+        ref.targetNodeClass = target->nodeClass;
+    }
+    if (!retval) {
+        retval |= addOneWayReferenceWithSession(server, (UA_Session *) UA_NULL, &ref);
+    }
+    
+    
+    UA_AddReferencesItem_deleteMembers(&ref);
+    return retval;
+}
+    
+
 /* Adds a one-way reference to the local nodestore */
-static UA_StatusCode
+UA_StatusCode
 addOneWayReferenceWithSession(UA_Server *server, UA_Session *session, const UA_AddReferencesItem *item) {
     const UA_Node *node = UA_NodeStore_get(server->nodestore, &item->sourceNodeId);
     if(!node)

+ 3 - 0
src/server/ua_server_internal.h

@@ -86,6 +86,9 @@ UA_AddNodesResult UA_Server_addNode(UA_Server *server, UA_Node *node, const UA_E
 UA_StatusCode UA_Server_addReferenceWithSession(UA_Server *server, UA_Session *session,
                                                 const UA_AddReferencesItem *item);
 
+UA_StatusCode addOneWayReferenceWithSession(UA_Server *server, UA_Session *session, 
+                                                   const UA_AddReferencesItem *item);
+
 UA_StatusCode UA_Server_addDelayedJob(UA_Server *server, UA_Job job);
 
 void UA_Server_deleteAllRepeatedJobs(UA_Server *server);

+ 2 - 2
src/server/ua_server_worker.c

@@ -163,7 +163,7 @@ struct IdentifiedJob {
 
 /**
  * The RepeatedJobs structure contains an array of jobs that are either executed with the same
- * repetition inverval. The linked list is sorted, so we can stop traversing when the first element
+ * repetition interval. The linked list is sorted, so we can stop traversing when the first element
  * has nextTime > now.
  */
 struct RepeatedJobs {
@@ -535,7 +535,7 @@ UA_StatusCode UA_Server_run_startup(UA_Server *server, UA_UInt16 nThreads, UA_Bo
 #endif
 
     /* Start the networklayers */
-    for(size_t i = 0; i <server->networkLayersSize; i++)
+    for(size_t i = 0; i < server->networkLayersSize; i++)
         server->networkLayers[i].start(server->networkLayers[i].nlHandle, &server->logger);
 
     return UA_STATUSCODE_GOOD;

+ 1 - 1
src/server/ua_services.h

@@ -141,7 +141,7 @@ void Service_Browse(UA_Server *server, UA_Session *session, const UA_BrowseReque
 
 /**
  * Used to request the next set of Browse or BrowseNext response information
- * that is too large to be sent in a single response. “Too large” in this
+ * that is too large to be sent in a single response. "Too large" in this
  * context means that the Server is not able to return a larger response or that
  * the number of results to return exceeds the maximum number of results to
  * return that was specified by the Client in the original Browse request.

+ 29 - 10
src/server/ua_services_view.c

@@ -45,7 +45,7 @@ static UA_StatusCode fillrefdescr(UA_NodeStore *ns, const UA_Node *curr, UA_Refe
    so, it is retrieved from the Nodestore. If not, null is returned. */
 static const UA_Node *relevant_node(UA_Server *server, UA_NodeStore *ns, const UA_BrowseDescription *descr,
                                     UA_Boolean return_all, UA_ReferenceNode *reference,
-                                    UA_NodeId *relevant, size_t relevant_count)
+                                    UA_NodeId *relevant, size_t relevant_count, UA_Boolean *isExternal)
 {
     if(reference->isInverse == UA_TRUE && descr->browseDirection == UA_BROWSEDIRECTION_FORWARD)
         return UA_NULL;
@@ -60,19 +60,19 @@ static const UA_Node *relevant_node(UA_Server *server, UA_NodeStore *ns, const U
         return UA_NULL;
     }
 is_relevant: ;
+	*isExternal = UA_FALSE;
 #ifdef UA_EXTERNAL_NAMESPACES
 	const UA_Node *node = NULL;
-	UA_Boolean isExternal = UA_FALSE;
 	size_t nsIndex;
 	for(nsIndex = 0; nsIndex < server->externalNamespacesSize; nsIndex++) {
 		if(reference->targetId.nodeId.namespaceIndex != server->externalNamespaces[nsIndex].index)
 			continue;
 		else{
-			isExternal = UA_TRUE;
+			*isExternal = UA_TRUE;
 			break;
 		}
 	}
-	if(isExternal == UA_FALSE){
+	if(*isExternal == UA_FALSE){
 		node = UA_NodeStore_get(ns, &reference->targetId.nodeId);
 	} else {
 		/*	prepare a read request in the external nodestore	*/
@@ -131,8 +131,8 @@ is_relevant: ;
 #endif
     if(node && descr->nodeClassMask != 0 && (node->nodeClass & descr->nodeClassMask) == 0) {
 #ifdef UA_EXTERNAL_NAMESPACES
-    	if(isExternal == UA_TRUE){
-    		;
+    	if(*isExternal == UA_TRUE){
+    		UA_ObjectNode_delete((UA_ObjectNode*)node);
     	} else
 #endif
     	UA_NodeStore_release(node);
@@ -303,19 +303,38 @@ static void browse(UA_Server *server, UA_Session *session, UA_NodeStore *ns, str
 
     /* loop over the node's references */
     size_t skipped = 0;
+    UA_Boolean isExternal = UA_FALSE;
     for(; referencesIndex < node->referencesSize && referencesCount < real_maxrefs; referencesIndex++) {
-        const UA_Node *current = relevant_node(server, ns, descr, all_refs, &node->references[referencesIndex],
-                                               relevant_refs, relevant_refs_size);
+    	isExternal = UA_FALSE;
+    	const UA_Node *current = relevant_node(server, ns, descr, all_refs, &node->references[referencesIndex],
+                                               relevant_refs, relevant_refs_size, &isExternal);
         if(!current)
             continue;
         if(skipped < continuationIndex) {
-            UA_NodeStore_release(current);
+#ifdef UA_EXTERNAL_NAMESPACES
+        	if(isExternal == UA_TRUE){
+        		/*	relevant_node returns a node malloced with UA_ObjectNode_new if it is external (there is no UA_Node_new function)	*/
+        		UA_ObjectNode_delete((UA_ObjectNode*)current);
+        	} else {
+        		UA_NodeStore_release(current);
+        	}
+#else
+        	UA_NodeStore_release(current);
+#endif
             skipped++;
             continue;
         }
         UA_StatusCode retval = fillrefdescr(ns, current, &node->references[referencesIndex], descr->resultMask,
                                             &result->references[referencesCount]);
-        UA_NodeStore_release(current);
+#ifdef UA_EXTERNAL_NAMESPACES
+        if(isExternal == UA_TRUE){
+        	UA_ObjectNode_delete((UA_ObjectNode*)current);
+        } else {
+        	UA_NodeStore_release(current);
+        }
+#else
+        	UA_NodeStore_release(current);
+#endif
         if(retval != UA_STATUSCODE_GOOD) {
             UA_Array_delete(result->references, &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], referencesCount);
             result->references = UA_NULL;

+ 2 - 1
src/ua_securechannel.c

@@ -25,7 +25,8 @@ void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel) {
     UA_Connection *c = channel->connection;
     if(c) {
         UA_Connection_detachSecureChannel(c);
-        c->close(c);
+        if(c->close)
+            c->close(c);
     }
     /* just remove the pointers and free the linked list (not the sessions) */
     struct SessionEntry *se;

+ 13 - 4
src/ua_util.h

@@ -49,10 +49,19 @@
 #define UA_assert(ignore) assert(ignore)
 
 /* Replace the macros with functions for custom allocators if necessary */
-#define UA_free(ptr) free(ptr)
-#define UA_malloc(size) malloc(size)
-#define UA_calloc(num, size) calloc(num, size)
-#define UA_realloc(ptr, size) realloc(ptr, size)
+#ifndef UA_free
+    #define UA_free(ptr) free(ptr)
+#endif
+#ifndef UA_malloc
+    #define UA_malloc(size) malloc(size)
+#endif
+#ifndef UA_calloc
+    #define UA_calloc(num, size) calloc(num, size)
+#endif
+#ifndef UA_realloc
+    #define UA_realloc(ptr, size) realloc(ptr, size)
+#endif
+
 #define UA_memcpy(dst, src, size) memcpy(dst, src, size)
 #define UA_memset(ptr, value, size) memset(ptr, value, size)
 

+ 24 - 15
tools/amalgamate.py

@@ -2,6 +2,7 @@ from __future__ import print_function
 import re
 import argparse
 import os.path
+import io
 
 parser = argparse.ArgumentParser()
 parser.add_argument('version', help='version to include')
@@ -19,20 +20,24 @@ includes = []
 
 is_c = False
 
+print ("Starting amalgamating file "+ args.outfile)
+
 for fname in args.inputs:
     if("util.h" in fname):
         is_c = True
         continue
-    with open(fname) as infile:
+    with io.open(fname, encoding="utf8") as infile:
+        print ("Integrating file '" + fname + "'...", end=""),
         for line in infile:
             res = include_re.match(line)
             if res:
                 inc = res.group(1)
                 if not inc in includes and not inc[0] == '"':
                     includes.append(inc)
+        print ("done."),
 
-file = open(args.outfile, 'w')
-file.write('''/* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN62541 SOURCES 
+file = io.open(args.outfile, 'w')
+file.write(u'''/* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN62541 SOURCES 
  * visit http://open62541.org/ for information about this software
  * Git-Revision: %s
  */
@@ -53,45 +58,49 @@ file.write('''/* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN62
  */\n\n''' % args.version)
 
 if not is_c:
-    file.write('''#ifndef %s
+    file.write(u'''#ifndef %s
 #define %s
 
 #ifdef __cplusplus
 extern "C" {
-#endif\n\n''' % (outname.upper() + "_H_", outname.upper() + "_H_") )
+#endif\n\n''' % (outname.upper() + u"_H_", outname.upper() + u"_H_") )
 
 if not is_c:
     for inc in includes:
-        file.write("#include " + inc + "\n")
+        file.write(u"#include " + inc + "\n")
 else:
-    file.write("#define UA_AMALGAMATE\n")
-    file.write('''#ifndef UA_DYNAMIC_LINKING
+    file.write(u"#define UA_AMALGAMATE\n")
+    file.write(u'''#ifndef UA_DYNAMIC_LINKING
 # define UA_DYNAMIC_LINKING
 #endif\n\n''')
     for fname in args.inputs:
         if "ua_config.h" in fname or "ua_util.h" in fname:
-            with open(fname) as infile:
+            with io.open(fname, encoding="utf8") as infile:
+                print ("Integrating file '" + fname + "'...", end=""),
                 for line in infile:
                     file.write(line)
-    file.write("#include \"" + outname + ".h\"\n")
+                print ("done."),
+    file.write(u"#include \"" + outname + ".h\"\n")
 
 for fname in args.inputs:
     if not "util.h" in fname:
-        with open(fname) as infile:
-            file.write("/*********************************** amalgamated original file \"" + fname + "\" ***********************************/\n")
+        with io.open(fname, encoding="utf8") as infile:
+            file.write(u"/*********************************** amalgamated original file \"" + fname + u"\" ***********************************/\n")
+            print ("Integrating file '" + fname + "'...", end=""),
             for line in infile:
                 inc_res = include_re.match(line)
                 guard_res = guard_re.match(line)
                 if not inc_res and not guard_res:
                     file.write(line)
+            print ("done."),
 
 if not is_c:
-    file.write('''
+    file.write(u'''
 #ifdef __cplusplus
 } // extern "C"
 #endif
 
-#endif /* %s */''' % (outname.upper() + "_H_"))
+#endif /* %s */''' % (outname.upper() + u"_H_"))
 file.close()
 
-print ("The size of "+args.outfile+" is "+ str(os.path.getsize(args.outfile)))
+print ("The size of "+args.outfile+" is "+ str(os.path.getsize(args.outfile))+" Bytes.")

+ 33 - 7
tools/generate_datatypes.py

@@ -160,8 +160,12 @@ class EnumerationType(object):
         return True
 
     def typedef_c(self):
+        if sys.version_info[0] < 3:
+            values = self.elements.iteritems()
+        else:
+            values = self.elements.items()
         return "typedef enum { \n    " + \
-            ",\n    ".join(map(lambda kv : kv[0].upper() + " = " + kv[1], self.elements.iteritems())) + \
+            ",\n    ".join(map(lambda kv : kv[0].upper() + " = " + kv[1], values)) + \
             "\n} " + self.name + ";"
 
     def typelayout_c(self, namespace_0, description, outname):
@@ -257,7 +261,11 @@ class StructType(object):
         if len(self.members) == 0:
             return "typedef void * " + self.name + ";"
         returnstr =  "typedef struct {\n"
-        for name, member in self.members.iteritems():
+        if sys.version_info[0] < 3:
+            values = self.members.iteritems()
+        else:
+            values = self.members.items()
+        for name, member in values:
             if member.isArray:
                 returnstr += "    UA_Int32 " + name + "Size;\n"
                 returnstr += "    " + member.memberType.name + " *" +name + ";\n"
@@ -291,7 +299,10 @@ class StructType(object):
                 before_endpos = "0"
                 thispos = "offsetof(%s, %s)" % (self.name, member.name)
                 if index > 0:
-                    before = self.members.values()[index-1]
+                    if sys.version_info[0] < 3:
+                        before = self.members.values()[index-1]
+                    else:
+                        before = list(self.members.values())[index-1]
                     before_endpos = "(offsetof(%s, %s)" % (self.name, before.name)
                     if before.isArray:
                         before_endpos += " + sizeof(void*))"
@@ -446,10 +457,16 @@ if args.enable_subscription_types:
 if args.namespace_id == 0 or args.ns0_types_xml:
     existing_types = OrderedDict([(t, BuiltinType(t)) for t in builtin_types])
 if args.ns0_types_xml:
-    OrderedDict(existing_types.items() + parseTypeDefinitions(args.ns0_types_xml[0], existing_types).items())
+    if sys.version_info[0] < 3:
+        OrderedDict(existing_types.items() + parseTypeDefinitions(args.ns0_types_xml[0], existing_types).items())
+    else:
+        OrderedDict(list(existing_types.items()) + list(parseTypeDefinitions(args.ns0_types_xml[0], existing_types).items()))
 types = parseTypeDefinitions(args.types_xml, existing_types)
 if args.namespace_id == 0:
-    types = OrderedDict(existing_types.items() + types.items())
+    if sys.version_info[0] < 3:
+        types = OrderedDict(existing_types.items() + types.items())
+    else:
+        types = OrderedDict(list(existing_types.items()) + list(types.items()))
 
 typedescriptions = {}
 if args.typedescriptions:
@@ -495,7 +512,12 @@ printh("#define " + outname.upper() + "_COUNT %s\n" % (str(len(types))))
 printh("extern UA_EXPORT const UA_DataType *" + outname.upper() + ";\n")
 
 i = 0
-for t in types.itervalues():
+if sys.version_info[0] < 3:
+    values = types.itervalues()
+else:
+    values = types.values()
+
+for t in values:
     if type(t) != BuiltinType:
         printh("")
         if t.description != "":
@@ -525,7 +547,11 @@ printc('''/**
 #include "ua_types.h"
 #include "''' + outname + '''_generated.h"\n
 const UA_DataType *''' + outname.upper() + ''' = (UA_DataType[]){''')
-for t in types.itervalues():
+if sys.version_info[0] < 3:
+    values = types.itervalues()
+else:
+    values = types.values()
+for t in values:
     printc("")
     printc("/* " + t.name + " */")
     if args.typedescriptions:

+ 29 - 0
tools/pyUANamespace/NodeID_AssumeExternal.txt

@@ -0,0 +1,29 @@
+i=2253
+i=2254
+i=2255
+i=2256
+i=2257
+i=2258
+i=2259
+i=2260
+i=2261
+i=2262
+i=2263
+i=2264
+i=2265
+i=2266
+i=2267
+i=2271
+i=2274
+i=2292
+i=2294
+i=2735
+i=2992
+i=2993
+i=2994
+i=2268
+i=274
+i=295
+i=296
+i=11715
+i=11492

+ 0 - 0
tools/pyUANamespace/NodeID_Blacklist.txt


+ 150 - 0
tools/pyUANamespace/README.md

@@ -0,0 +1,150 @@
+pyUANamespace
+=============
+
+pyUANamespace is a collection of python 2 scripts that can parse OPC UA XML Namespace definition files and transform them into a class representation. This facilitates both reprinting the namespace in a different non-XML format (such as C-Code or DOT) and analysis of the namespace structure.
+
+
+
+### Documentation
+
+The pyUANamespace implementation has been contributed by a research project of the chair for Process Control Systems Engineering of the TU Dresden. It was not strictly speaking created as a C generator, but could be easily modified to fullfill this role for open62541.
+
+## Functionality in open62541
+
+In open62541, the linked python namespace generated by the pyUANamespace classes are used to print C-Code that will automatically initialize a server. Apart from parsing XML, most classes also have a printOpen6251Header() or printOpen6251Header_Subtype() function that can reprint the node as C Code compatible with the project.
+
+This function has been wrapped into the generate_open62541CCode.py program, which implements the compiler and option checking relevant to this task. The program is called as follows:
+
+```bash
+$ python generate_open62541CCode.py /path/to/NodeSet.xml /path/to/outputfile.c
+```
+
+Several options have been made available to further facilitate header generation. Calling the script without arguments will produce a usage helper listing all available options.
+
+# Overwriting NodeSet definitions
+
+Most notably, any number of XML files can be passed. The latest XML definition of a node found is used.
+
+```bash
+$ python generate_open62541CCode.py /path/to/NodeSet0.xml /path/to/OverwriteNodeSet0.xml /path/to/outputfile.c
+```
+
+# Blacklisting Nodes
+
+If a set of nodes is not to be contained in the namespace, they can be specified as a blacklist file containing one nodeId per line in the following format:
+
+```
+ns=1;id=2323
+id=11122;
+```
+
+This file can be passed to the compiler, which will remove these nodes prior to linking the namespace.
+
+```bash
+$ python generate_open62541CCode.py -b blacklist.txt /path/to/NodeSet.xml /path/to/outputfile.c
+```
+
+In this particular example, nodes `ns=1;id=2323` and `ns=0;id=11122` will be removed from the namespace (which may invalidate other nodes referring to them).
+
+# Ignoring Nodes
+
+Blacklisting removes nodes, which means that any other nodes referring to these nodes will contain invalid references. If a namespace should be generated that can use all datatypes, objectstypes, etc., but should only print specific nodes into the C Header, a set of nodes can be ignored. This will cause the compiler to use them in the linked namespace where other nodes can use them (e.g. in buildEncodingRules()), but they will not appear as part of the header file.
+
+Ignorelists have the same format as blacklists and are passed to the compiler like so:.
+
+```bash
+$ python generate_open62541CCode.py -i ignorelist.txt /path/to/NodeSet.xml /path/to/outputfile.c
+```
+
+Given the blacklist example, the nodes `ns=1;id=2323` and `ns=0;id=11122` will not be part of the header, but other nodes may attempt to create references to them or use them as dataTypes.
+
+# Supressing attributes
+
+Most of OPC UA Namespaces depend heavily on strings. These can bloat up memory usage in applications where memory is a critical ressource. The compiler can be instructed to suppress allocation for certain attributes, which will be initialized to sensible defaults or NULL pointers where applicable.
+
+```bash
+$ python generate_open62541CCode.py -s browsename -s displayname -s nodeid /path/to/NodeSet.xml /path/to/outputfile.c
+```
+
+Currently, the following base attributes of nodes can be suppressed:
+- browseName
+- displayName
+- description
+- nodeId
+- writeMask
+- userWriteMask
+
+Further attributes may be added at a later point depending on demand.
+
+## Core functionality
+
+OPC UA node types, base data types and references are described in ua_node_types.py and ua_builtin_types.py. These classes are primarily intended to act as part of an AST to parse OPC UA Namespace description files. They implement a hierarchic/rekursive parsing of XML DOM objects, supplementing their respective properties from the XML description.
+
+A manager class called ua_namespace is included in the respective source file. This class does _not_ correspond to a OPC UA Namespace. It is an aggregator and manager for nodes and references which may belong to any number of namespaces. This class includes extensive parsing/validation to ensure that a complete and consistent namespace is generated.
+
+## Namespace compilation internals
+
+Compiling a namespace consists of the following steps:
+- Read one or more XML definitions
+- Link references to actual nodes (also includes references to dataTypes, etc.)
+- Sanitize/Remove any nodes and references that could not be properly parsed
+- Derive encoding rules for datatypes
+- Parse/Allocate variable values according to their dataType definitions
+
+
+Reading and parsing XML files is handled by ua_namespace.parseXML(/path/to/file.xml). It is the first part of a multipass compiler that will create all nodes contained in the XML description. 
+
+During the reading of XML files, nodes will attempt to parse any attributes they own, but not refer to any other nodes. References will be kept as XML descriptions. Any number of XML files can be read in this phase. __NOTE__: In the open62541 (this) implementation, duplicate nodes (same NodeId) are allowed. The last definition encountered will be kept. This allows overwriting specific nodes of a much larger XML file to with implementation specific nodes.
+
+The next phase of the compilation is to link all references. The phase is called by ua_namespace.linkOpenPointers(). All references will attempt to locate their target() node in the namespace and point to it.
+
+During the sanitation phase called by ua_namespace.sanitize(), nodes check themselves for invalid attributes. Most notably any references that could not be resolved to a node will be removed from the nodes.
+
+When calling ua_namespace.buildEncodingRules(), dataType nodes are examined to determine if and how the can be encoded as a serialization of OPC UA builtin types as well as their aliases. 
+
+The following fragment of a variable value can illustrate the necessity for determining encoding rules:
+```xml
+<Argument>
+    <Name>ServerHandles</Name>
+    <DataType>
+    <Identifier>i=7</Identifier>
+    </DataType>
+    <ValueRank>1</ValueRank>
+    <ArrayDimensions />
+    <Description p5:nil="true" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" />
+</Argument>
+```
+The tags body, TypeId, Identifier, and Argument are aliases for builtin encodings or structures thereof. Without knowing which type they represent, an appropriate value class (and with that a parser) cannot be created. pyUANamespace will resolve this specific case by determining the encoding as follows:
+```
+LastMethodOutputArguments : Argument -> i=296
++ [['Name', ['String']], ['DataType', ['NodeId']], ['ValueRank', ['Int32']], ['ArrayDimensions', ['UInt32']], ['Description', ['LocalizedText']]] (already analyzed)
+
+```
+
+DataTypes that cannot be encoded as a definite serial object (e.g. by having a member of NumericType, but not a specific one), will have their isEncodable() attribute disabled. All dataTypes that complete this node can be used to effectively determine the size and serialization properties of any variables.
+
+Having encoding rules means that data can now be parsed when a <Value> tag is encountered in a description. Calling ua_namespace.allocateVariables() will do just that for any variable node that hols XML Values. 
+
+The result of this compilation is a completely linked and instantiated OPC UA namespace.
+
+An example compiler can be built as follows:
+```python
+class testing:
+  def __init__(self):
+    self.namespace = opcua_namespace("testing")
+
+    log(self, "Phase 1: Reading XML file nodessets")
+    self.namespace.parseXML("Opc.Ua.NodeSet2.xml")
+    self.namespace.parseXML("DeviceNodesSet.xml")
+    self.namespace.parseXML("MyNodesSet.xml")
+    
+    log(self, "Phase 2: Linking address space references and datatypes")
+    self.namespace.linkOpenPointers()
+    self.namespace.sanitize()
+
+    log(self, "Phase 3: Comprehending DataType encoding rules")
+    self.namespace.buildEncodingRules()
+
+    log(self, "Phase 4: Allocating variable value data")
+    self.namespace.allocateVariables()
+```

+ 190 - 0
tools/pyUANamespace/generate_open62541CCode.py

@@ -0,0 +1,190 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+###
+### Author:  Chris Iatrou (ichrispa@core-vector.net)
+### Version: rev 13
+###
+### This program was created for educational purposes and has been
+### contributed to the open62541 project by the author. All licensing
+### terms for this source is inherited by the terms and conditions
+### specified for by the open62541 project (see the projects readme
+### file for more information on the LGPL terms and restrictions).
+###
+### This program is not meant to be used in a production environment. The
+### author is not liable for any complications arising due to the use of
+### this program.
+###
+
+from sys import argv, exit
+from os import path
+from ua_namespace import *
+from logger import *
+
+def usage():
+  print "Script usage:"
+  print "generate_open62541CCode [-i <ignorefile> | -b <blacklistfile>] <namespace XML> [namespace.xml[ namespace.xml[...]]] <output file>"
+  print ""
+  print "generate_open62541CCode will first read all XML files passed on the command line, then "
+  print "link and check the namespace. All nodes that fullfill the basic requirements will then be"
+  print "printed as C-Code intended to be included in the open62541 OPC-UA Server that will"
+  print "initialize the corresponding name space."
+  print ""
+  print "Manditory Arguments:"
+  print "<namespace XML>    At least one Namespace XML file must be passed."
+  print "<output file>      The basename for the <output file>.c and <output file>.h files to be generated."
+  print "                   This will also be the function name used in the header and c-file."
+  print ""
+  print ""
+  print "Additional Arguments:"
+  print """   -i <ignoreFile>     Loads a list of NodeIDs stored in ignoreFile (one NodeID per line)
+                       The compiler will assume that these Nodes have been created externally
+                       and not generate any code for them. They will however be linked to
+                       from other nodes."""
+  print """   -b <blacklistFile>  Loads a list of NodeIDs stored in blacklistFile (one NodeID per line)
+                       Any of the nodeIds encountered in this file will be removed from the namespace
+                       prior to compilation. Any references to these nodes will also be removed"""
+  print """   -s <attribute>  Suppresses the generation of some node attributes. Currently supported
+                       options are 'description', 'browseName', 'displayName', 'writeMask', 'userWriteMask'
+                       and 'nodeid'."""
+  print """   namespaceXML Any number of namespace descriptions in XML format. Note that the
+                       last description of a node encountered will be used and all prior definitions
+                       are discarded."""
+
+if __name__ == '__main__':
+  # Check if the parameters given correspond to actual files
+  infiles = []
+  ouffile = ""
+  ignoreFiles = []
+  blacklistFiles = []
+  supressGenerationOfAttribute=[]
+
+  GLOBAL_LOG_LEVEL = LOG_LEVEL_DEBUG
+
+  arg_isIgnore    = False
+  arg_isBlacklist = False
+  arg_isSupress   = False
+  if len(argv) < 2:
+    usage()
+    exit(1)
+  for filename in argv[1:-1]:
+    if arg_isIgnore:
+      arg_isIgnore = False
+      if path.exists(filename):
+        ignoreFiles.append(filename)
+      else:
+        log(None, "File " + str(filename) + " does not exist.", LOG_LEVEL_ERROR)
+        usage()
+        exit(1)
+    elif arg_isBlacklist:
+      arg_isBlacklist = False
+      if path.exists(filename):
+        blacklistFiles.append(filename)
+      else:
+        log(None, "File " + str(filename) + " does not exist.", LOG_LEVEL_ERROR)
+        usage()
+        exit(1)
+    elif arg_isSupress:
+      arg_isSupress = False
+      supressGenerationOfAttribute.append(filename.lower())
+    else:
+      if path.exists(filename):
+        infiles.append(filename)
+      elif filename.lower() == "-i" or filename.lower() == "--ignore" :
+        arg_isIgnore = True
+      elif filename.lower() == "-b" or filename.lower() == "--blacklist" :
+        arg_isBlacklist = True
+      elif filename.lower() == "-s" or filename.lower() == "--suppress" :
+        arg_isSupress = True
+      else:
+        log(None, "File " + str(filename) + " does not exist.", LOG_LEVEL_ERROR)
+        usage()
+        exit(1)
+
+  # Creating the header is tendious. We can skip the entire process if
+  # the header exists.
+  #if path.exists(argv[-1]+".c") or path.exists(argv[-1]+".h"):
+  #  log(None, "File " + str(argv[-1]) + " does already exists.", LOG_LEVEL_INFO)
+  #  log(None, "Header generation will be skipped. Delete the header and rerun this script if necessary.", LOG_LEVEL_INFO)
+  #  exit(0)
+
+  # Open the output file
+  outfileh = open(argv[-1]+".h", r"w+")
+  outfilec = open(argv[-1]+".c", r"w+")
+
+  # Create a new namespace
+  # Note that the name is actually completely symbolic, it has no other
+  # function but to distinguish this specific class.
+  # A namespace class acts as a container for nodes. The nodes may belong
+  # to any number of different OPC-UA namespaces.
+  ns = opcua_namespace("open62541")
+
+  # Parse the XML files
+  for xmlfile in infiles:
+    log(None, "Parsing " + str(xmlfile), LOG_LEVEL_INFO)
+    ns.parseXML(xmlfile)
+
+  # Remove blacklisted nodes from the namespace
+  # Doing this now ensures that unlinkable pointers will be cleanly removed
+  # during sanitation.
+  for blacklist in blacklistFiles:
+    bl = open(blacklist, "r")
+    for line in bl.readlines():
+      line = line.replace(" ","")
+      id = line.replace("\n","")
+      if ns.getNodeByIDString(id) == None:
+        log(None, "Can't blacklist node, namespace does currently not contain a node with id " + str(id), LOG_LEVEL_WARN)
+      else:
+        ns.removeNodeById(line)
+    bl.close()
+
+  # Link the references in the namespace
+  log(None, "Linking namespace nodes and references", LOG_LEVEL_INFO)
+  ns.linkOpenPointers()
+
+  # Remove nodes that are not printable or contain parsing errors, such as
+  # unresolvable or no references or invalid NodeIDs
+  ns.sanitize()
+
+  # Parse Datatypes in order to find out what the XML keyed values actually
+  # represent.
+  # Ex. <rpm>123</rpm> is not encodable
+  #     only after parsing the datatypes, it is known that
+  #     rpm is encoded as a double
+  log(None, "Building datatype encoding rules", LOG_LEVEL_INFO)
+  ns.buildEncodingRules()
+
+  # Allocate/Parse the data values. In order to do this, we must have run
+  # buidEncodingRules.
+  log(None, "Allocating variables", LOG_LEVEL_INFO)
+  ns.allocateVariables()
+
+  # Users may have manually defined some nodes in their code already (such as serverStatus).
+  # To prevent those nodes from being reprinted, we will simply mark them as already
+  # converted to C-Code. That way, they will still be reffered to by other nodes, but
+  # they will not be created themselves.
+  ignoreNodes = []
+  for ignore in ignoreFiles:
+    ig = open(ignore, "r")
+    for line in ig.readlines():
+      line = line.replace(" ","")
+      id = line.replace("\n","")
+      if ns.getNodeByIDString(id) == None:
+        log(None, "Can't ignore node, Namespace does currently not contain a node with id " + str(id), LOG_LEVEL_WARN)
+      else:
+        ignoreNodes.append(ns.getNodeByIDString(id))
+    ig.close()
+
+  # Create the C Code
+  log(None, "Generating Header", LOG_LEVEL_INFO)
+  # Returns a tuple of (["Header","lines"],["Code","lines","generated"])
+  generatedCode=ns.printOpen62541Header(ignoreNodes, supressGenerationOfAttribute, outfilename=path.basename(argv[-1]))
+  for line in generatedCode[0]:
+    outfileh.write(line+"\n")
+  for line in generatedCode[1]:
+    outfilec.write(line+"\n")
+ 
+  outfilec.close()
+  outfileh.close()
+
+  exit(0)

+ 45 - 0
tools/pyUANamespace/logger.py

@@ -0,0 +1,45 @@
+#!/usr/bin/env/python
+# -*- coding: utf-8 -*-
+
+###
+### Author:  Chris Iatrou (ichrispa@core-vector.net)
+### Version: rev 13
+###
+### This program was created for educational purposes and has been
+### contributed to the open62541 project by the author. All licensing
+### terms for this source is inherited by the terms and conditions
+### specified for by the open62541 project (see the projects readme
+### file for more information on the LGPL terms and restrictions).
+###
+### This program is not meant to be used in a production environment. The
+### author is not liable for any complications arising due to the use of
+### this program.
+###
+
+import inspect
+
+###
+### Tidy logging helpers
+###
+
+LOG_LEVEL_DEBUG  = 4
+LOG_LEVEL_INFO   = 2
+LOG_LEVEL_WARN   = 1
+LOG_LEVEL_ERROR  = 0
+LOG_LEVEL_SILENT = -1
+
+# Change the following to filter logging output
+GLOBAL_LOG_LEVEL = LOG_LEVEL_SILENT
+
+def log(callee, logstr, level=LOG_LEVEL_DEBUG):
+  prefixes = { LOG_LEVEL_DEBUG : "DBG: ",
+               LOG_LEVEL_INFO  : "INF: ",
+               LOG_LEVEL_WARN  : "WRN: ",
+               LOG_LEVEL_ERROR : "ERR: ",
+               LOG_LEVEL_SILENT: ""
+            }
+  if level <= GLOBAL_LOG_LEVEL:
+    if prefixes.has_key(level):
+      print str(prefixes[level]) + callee.__class__.__name__ + "." + inspect.stack()[1][3] +  "(): " + logstr
+    else:
+      print callee.__class__.__name__  + "." + inspect.stack()[1][3] + "(): " + logstr

+ 146 - 0
tools/pyUANamespace/open62541_MacroHelper.py

@@ -0,0 +1,146 @@
+#!/usr/bin/env/python
+# -*- coding: utf-8 -*-
+
+###
+### Author:  Chris Iatrou (ichrispa@core-vector.net)
+### Version: rev 13
+###
+### This program was created for educational purposes and has been
+### contributed to the open62541 project by the author. All licensing
+### terms for this source is inherited by the terms and conditions
+### specified for by the open62541 project (see the projects readme
+### file for more information on the LGPL terms and restrictions).
+###
+### This program is not meant to be used in a production environment. The
+### author is not liable for any complications arising due to the use of
+### this program.
+###
+
+from logger import *
+from ua_constants import *
+
+__unique_item_id = 0
+
+class open62541_MacroHelper():
+  def __init__(self, supressGenerationOfAttribute=[]):
+    self.supressGenerationOfAttribute = supressGenerationOfAttribute
+
+  def getCreateExpandedNodeIDMacro(self, node):
+    if node.id().i != None:
+      return "UA_EXPANDEDNODEID_NUMERIC(" + str(node.id().ns) + ", " + str(node.id().i) + ")"
+    elif node.id().s != None:
+      return "UA_EXPANDEDNODEID_STRING("  + str(node.id().ns) + ", " + node.id().s + ")"
+    elif node.id().b != None:
+      log(self, "NodeID Generation macro for bytestrings has not been implemented.")
+      return ""
+    elif node.id().g != None:
+      log(self, "NodeID Generation macro for guids has not been implemented.")
+      return ""
+    else:
+      return ""
+
+  def getCreateNodeIDMacro(self, node):
+    if node.id().i != None:
+      return "UA_NODEID_NUMERIC(" + str(node.id().ns) + ", " + str(node.id().i) + ")"
+    elif node.id().s != None:
+      return "UA_NODEID_STRING("  + str(node.id().ns) + ", " + node.id().s + ")"
+    elif node.id().b != None:
+      log(self, "NodeID Generation macro for bytestrings has not been implemented.")
+      return ""
+    elif node.id().g != None:
+      log(self, "NodeID Generation macro for guids has not been implemented.")
+      return ""
+    else:
+      return ""
+
+  def getCreateStandaloneReference(self, sourcenode, reference):
+  # As reference from open62541 (we need to alter the attributes)
+  #    UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId, const UA_NodeId refTypeId,
+  #                                   const UA_ExpandedNodeId targetId)
+    code = []
+    #refid = "ref_" + reference.getCodePrintableID()
+    #code.append("UA_AddReferencesItem " + refid + ";")
+    #code.append("UA_AddReferencesItem_init(&" + refid + ");")
+    #code.append(refid + ".sourceNodeId = " + self.getCreateNodeIDMacro(sourcenode) + ";")
+    #code.append(refid + ".referenceTypeId = " + self.getCreateNodeIDMacro(reference.referenceType()) + ";")
+    #if reference.isForward():
+      #code.append(refid + ".isForward = UA_TRUE;")
+    #else:
+      #code.append(refid + ".isForward = UA_FALSE;")
+    #code.append(refid + ".targetNodeId = " + self.getCreateExpandedNodeIDMacro(reference.target()) + ";")
+    #code.append("addOneWayReferenceWithSession(server, (UA_Session *) UA_NULL, &" + refid + ");")
+    
+    if reference.isForward():
+      code.append("UA_Server_AddMonodirectionalReference(server, " + self.getCreateNodeIDMacro(sourcenode) + ", " + self.getCreateExpandedNodeIDMacro(reference.target()) + ", " + self.getCreateNodeIDMacro(reference.referenceType()) + ", UA_TRUE);")
+    else:
+      code.append("UA_Server_AddMonodirectionalReference(server, " + self.getCreateNodeIDMacro(sourcenode) + ", " + self.getCreateExpandedNodeIDMacro(reference.target()) + ", " + self.getCreateNodeIDMacro(reference.referenceType()) + ", UA_FALSE);")
+    
+    return code
+
+  def getCreateNode(self, node):
+    nodetype = ""
+    code = []
+
+    code.append("// Node: " + str(node) + ", " + str(node.browseName()))
+
+    if node.nodeClass() == NODE_CLASS_OBJECT:
+      nodetype = "UA_ObjectNode"
+    elif node.nodeClass() == NODE_CLASS_VARIABLE:
+      nodetype = "UA_VariableNode"
+    elif node.nodeClass() == NODE_CLASS_METHOD:
+      nodetype = "UA_MethodNode"
+    elif node.nodeClass() == NODE_CLASS_OBJECTTYPE:
+      nodetype = "UA_ObjectTypeNode"
+    elif node.nodeClass() == NODE_CLASS_REFERENCETYPE:
+      nodetype = "UA_ReferenceTypeNode"
+    elif node.nodeClass() == NODE_CLASS_VARIABLETYPE:
+      nodetype = "UA_VariableTypeNode"
+    elif node.nodeClass() == NODE_CLASS_DATATYPE:
+      nodetype = "UA_DataTypeNode"
+    elif node.nodeClass() == NODE_CLASS_VIEW:
+      nodetype = "UA_ViewNode"
+    elif node.nodeClass() == NODE_CLASS_METHODTYPE:
+      nodetype = "UA_MethodTypeNode"
+    else:
+      nodetype = "UA_NodeTypeNotFoundorGeneric"
+
+    code.append(nodetype + " *" + node.getCodePrintableID() + " = " + nodetype + "_new();")
+    if not "browsename" in self.supressGenerationOfAttribute:
+      code.append(node.getCodePrintableID() + "->browseName = UA_QUALIFIEDNAME_ALLOC(" +  str(node.id().ns) + ", \"" + node.browseName() + "\");")
+    if not "displayname" in self.supressGenerationOfAttribute:
+      code.append(node.getCodePrintableID() + "->displayName = UA_LOCALIZEDTEXT_ALLOC(\"en_US\", \"" +  node.displayName() + "\");")
+    if not "description" in self.supressGenerationOfAttribute:
+      code.append(node.getCodePrintableID() + "->description = UA_LOCALIZEDTEXT_ALLOC(\"en_US\", \"" +  node.description() + "\");")
+
+    if not "writemask" in self.supressGenerationOfAttribute:
+        if node.__node_writeMask__ != 0:
+          code.append(node.getCodePrintableID() + "->writeMask = (UA_Int32) " +  str(node.__node_writeMask__) + ";")
+    if not "userwritemask" in self.supressGenerationOfAttribute:
+        if node.__node_userWriteMask__ != 0:
+          code.append(node.getCodePrintableID() + "->userWriteMask = (UA_Int32) " + str(node.__node_userWriteMask__) + ";")
+    #FIXME: Allocate descriptions, etc.
+
+    if not "nodeid" in self.supressGenerationOfAttribute:
+      if node.id().ns != 0:
+        code.append(node.getCodePrintableID() + "->nodeId.namespaceIndex = " + str(node.id().ns) + ";")
+      if node.id().i != None:
+        code.append(node.getCodePrintableID() + "->nodeId.identifier.numeric = " + str(node.id().i) + ";")
+      elif node.id().b != None:
+        code.append(node.getCodePrintableID() + "->nodeId.identifierType = UA_NODEIDTYPE_BYTESTRING;")
+        log(self, "ByteString IDs for nodes has not been implemented yet.", LOG_LEVEL_ERROR)
+        return []
+      elif node.id().g != None:
+        #<jpfr> the string is sth like { .length = 111, .data = <ptr> }
+        #<jpfr> there you _may_ alloc the <ptr> on the heap
+        #<jpfr> for the guid, just set it to {.data1 = 111, .data2 = 2222, ....
+        code.append(node.getCodePrintableID() + "->nodeId.identifierType = UA_NODEIDTYPE_GUID;")
+        log(self, "GUIDs for nodes has not been implemented yet.", LOG_LEVEL_ERROR)
+        return []
+      elif node.id().s != None:
+        code.append(node.getCodePrintableID() + "->nodeId.identifierType = UA_NODEIDTYPE_STRING;")
+        code.append(node.getCodePrintableID() + "->nodeId.identifier.numeric = UA_STRING_ALLOC(\"" + str(node.id().i) + "\");")
+      else:
+        log(self, "Node ID is not numeric, bytestring, guid or string. I do not know how to create c code for that...", LOG_LEVEL_ERROR)
+        return []
+
+    return code

Diferenças do arquivo suprimidas por serem muito extensas
+ 1083 - 0
tools/pyUANamespace/ua_builtin_types.py


+ 57 - 0
tools/pyUANamespace/ua_constants.py

@@ -0,0 +1,57 @@
+#!/usr/bin/env/python
+# -*- coding: utf-8 -*-
+
+###
+### Author:  Chris Iatrou (ichrispa@core-vector.net)
+### Version: rev 13
+###
+### This program was created for educational purposes and has been 
+### contributed to the open62541 project by the author. All licensing 
+### terms for this source is inherited by the terms and conditions
+### specified for by the open62541 project (see the projects readme
+### file for more information on the LGPL terms and restrictions).
+###
+### This program is not meant to be used in a production environment. The
+### author is not liable for any complications arising due to the use of
+### this program.
+###
+
+NODE_CLASS_GENERERIC        = 0
+NODE_CLASS_OBJECT           = 1
+NODE_CLASS_VARIABLE         = 2
+NODE_CLASS_METHOD           = 4
+NODE_CLASS_OBJECTTYPE       = 8
+NODE_CLASS_VARIABLETYPE     = 16
+NODE_CLASS_REFERENCETYPE    = 32
+NODE_CLASS_DATATYPE         = 64
+NODE_CLASS_VIEW             = 128
+
+# Not in OPC-UA, but exists in XML
+NODE_CLASS_METHODTYPE       = 256
+
+##
+## Numeric codes used to encode binary type fields:
+##
+BUILTINTYPE_TYPEID_EXTENSIONOBJECT = 1
+BUILTINTYPE_TYPEID_LOCALIZEDTEXT = 2
+BUILTINTYPE_TYPEID_EXPANDEDNODEID = 3
+BUILTINTYPE_TYPEID_NODEID = 4
+BUILTINTYPE_TYPEID_DATETIME = 5
+BUILTINTYPE_TYPEID_QUALIFIEDNAME = 6
+BUILTINTYPE_TYPEID_STATUSCODE = 7
+BUILTINTYPE_TYPEID_GUID = 8
+BUILTINTYPE_TYPEID_BOOLEAN = 9
+BUILTINTYPE_TYPEID_BYTE = 10
+BUILTINTYPE_TYPEID_SBYTE = 11
+BUILTINTYPE_TYPEID_INT16 = 12
+BUILTINTYPE_TYPEID_UINT16 = 13
+BUILTINTYPE_TYPEID_INT32 = 14
+BUILTINTYPE_TYPEID_UINT32 = 15
+BUILTINTYPE_TYPEID_INT64 = 16
+BUILTINTYPE_TYPEID_UINT64 = 17
+BUILTINTYPE_TYPEID_FLOAT = 18
+BUILTINTYPE_TYPEID_DOUBLE = 19
+BUILTINTYPE_TYPEID_STRING = 20
+BUILTINTYPE_TYPEID_XMLELEMENT = 21
+BUILTINTYPE_TYPEID_BYTESTRING = 22
+BUILTINTYPE_TYPEID_DIAGNOSTICINFO = 23

+ 668 - 0
tools/pyUANamespace/ua_namespace.py

@@ -0,0 +1,668 @@
+#!/usr/bin/env/python
+# -*- coding: utf-8 -*-
+
+###
+### Author:  Chris Iatrou (ichrispa@core-vector.net)
+### Version: rev 13
+###
+### This program was created for educational purposes and has been
+### contributed to the open62541 project by the author. All licensing
+### terms for this source is inherited by the terms and conditions
+### specified for by the open62541 project (see the projects readme
+### file for more information on the LGPL terms and restrictions).
+###
+### This program is not meant to be used in a production environment. The
+### author is not liable for any complications arising due to the use of
+### this program.
+###
+
+
+from time import struct_time, strftime, strptime, mktime
+from struct import pack as structpack
+
+from logger import *;
+from ua_builtin_types import *;
+from ua_node_types import *;
+from open62541_MacroHelper import open62541_MacroHelper
+
+def getNextElementNode(xmlvalue):
+  if xmlvalue == None:
+    return None
+  xmlvalue = xmlvalue.nextSibling
+  while not xmlvalue == None and not xmlvalue.nodeType == xmlvalue.ELEMENT_NODE:
+    xmlvalue = xmlvalue.nextSibling
+  return xmlvalue
+
+###
+### Namespace Organizer
+###
+
+class opcua_namespace():
+  """ Class holding and managing a set of OPCUA nodes.
+
+      This class handles parsing XML description of namespaces, instantiating
+      nodes, linking references, graphing the namespace and compiling a binary
+      representation.
+
+      Note that nodes assigned to this class are not restricted to having a
+      single namespace ID. This class represents the entire physical address
+      space of the binary representation and all nodes that are to be included
+      in that segment of memory.
+  """
+  nodes = []
+  nodeids = {}
+  aliases = {}
+  __linkLater__ = []
+  __binaryIndirectPointers__ = []
+  name = ""
+  knownNodeTypes = ""
+
+  def __init__(self, name):
+    self.nodes = []
+    self.knownNodeTypes = ['variable', 'object', 'method', 'referencetype', \
+                           'objecttype', 'variabletype', 'methodtype', \
+                           'datatype', 'referencetype', 'aliases']
+    self.name = name
+    self.nodeids = {}
+    self.aliases = {}
+    self.__binaryIndirectPointers__ = []
+
+  def linkLater(self, pointer):
+    """ Called by nodes or references who have parsed an XML reference to a
+        node represented by a string.
+
+        No return value
+
+        XML String representations of references have the form 'i=xy' or
+        'ns=1;s="This unique Node"'. Since during the parsing of this attribute
+        only a subset of nodes are known/parsed, this reference string cannot be
+        linked when encountered.
+
+        References register themselves with the namespace to have their target
+        attribute (string) parsed by linkOpenPointers() when all nodes are
+        created, so that target can be dereferenced an point to an actual node.
+    """
+    self.__linkLater__.append(pointer)
+
+  def getUnlinkedPointers(self):
+    """ Return the list of references registered for linking during the next call
+        of linkOpenPointers()
+    """
+    return self.__linkLater__
+
+  def unlinkedItemCount(self):
+    """ Returns the number of unlinked references that will be processed during
+        the next call of linkOpenPointers()
+    """
+    return len(self.__linkLater__)
+
+  def buildAliasList(self, xmlelement):
+    """ Parses the <Alias> XML Element present in must XML NodeSet definitions.
+
+        No return value
+
+        Contents the Alias element are stored in a dictionary for further
+        dereferencing during pointer linkage (see linkOpenPointer()).
+    """
+    if not xmlelement.tagName == "Aliases":
+      log(self, "XMLElement passed is not an Aliaslist", LOG_LEVEL_ERROR)
+      return
+    for al in xmlelement.childNodes:
+      if al.nodeType == al.ELEMENT_NODE:
+        if al.hasAttribute("Alias"):
+          aliasst = al.getAttribute("Alias")
+          aliasnd = unicode(al.firstChild.data)
+          if not self.aliases.has_key(aliasst):
+            self.aliases[aliasst] = aliasnd
+            log(self, "Added new alias \"" + str(aliasst) + "\" == \"" + str(aliasnd) + "\"")
+          else:
+            if self.aliases[aliasst] != aliasnd:
+              log(self, "Alias definitions for " + aliasst + " differ. Have " + self.aliases[aliasst] + " but XML defines " + aliasnd + ". Keeping current definition.", LOG_LEVEL_ERROR)
+
+  def getNodeByBrowseName(self, idstring):
+    """ Returns the first node in the nodelist whose browseName matches idstring.
+    """
+    matches = []
+    for n in self.nodes:
+      if idstring==str(n.browseName()):
+        matches.append(n)
+    if len(matches) > 1:
+      log(self, "Found multiple nodes with same ID!?", LOG_LEVEL_ERROR)
+    if len(matches) == 0:
+      return None
+    else:
+      return matches[0]
+
+  def getNodeByIDString(self, idstring):
+    """ Returns the first node in the nodelist whose id string representation
+        matches idstring.
+    """
+    matches = []
+    for n in self.nodes:
+      if idstring==str(n.id()):
+        matches.append(n)
+    if len(matches) > 1:
+      log(self, "Found multiple nodes with same ID!?", LOG_LEVEL_ERROR)
+    if len(matches) == 0:
+      return None
+    else:
+      return matches[0]
+
+  def createNode(self, ndtype, xmlelement):
+    """ createNode is instantiates a node described by xmlelement, its type being
+        defined by the string ndtype.
+
+        No return value
+
+        If the xmlelement is an <Alias>, the contents will be parsed and stored
+        for later dereferencing during pointer linking (see linkOpenPointers).
+
+        Recognized types are:
+        * UAVariable
+        * UAObject
+        * UAMethod
+        * UAView
+        * UAVariableType
+        * UAObjectType
+        * UAMethodType
+        * UAReferenceType
+        * UADataType
+
+        For every recognized type, an appropriate node class is added to the node
+        list of the namespace. The NodeId of the given node is created and parsing
+        of the node attributes and elements is delegated to the parseXML() and
+        parseXMLSubType() functions of the instantiated class.
+
+        If the NodeID attribute is non-unique in the node list, the creation is
+        deferred and an error is logged.
+    """
+    if not isinstance(xmlelement, dom.Element):
+      log(self,  "Error: Can not create node from invalid XMLElement", LOG_LEVEL_ERROR)
+      return
+
+    # An ID is manditory for everything but aliases!
+    id = None
+    for idname in ['NodeId', 'NodeID', 'nodeid']:
+      if xmlelement.hasAttribute(idname):
+        id = xmlelement.getAttribute(idname)
+    if ndtype == 'aliases':
+      self.buildAliasList(xmlelement)
+      return
+    elif id == None:
+      log(self,  "Error: XMLElement has no id, node will not be created!", LOG_LEVEL_INFO)
+      return
+    else:
+      id = opcua_node_id_t(id)
+
+    if self.nodeids.has_key(str(id)):
+      # Normal behavior: Do not allow duplicates, first one wins
+      #log(self,  "XMLElement with duplicate ID " + str(id) + " found, node will not be created!", LOG_LEVEL_ERROR)
+      #return
+      # Open62541 behavior for header generation: Replace the duplicate with the new node
+      log(self,  "XMLElement with duplicate ID " + str(id) + " found, node will be replaced!", LOG_LEVEL_INFO)
+      nd = self.getNodeByIDString(str(id))
+      self.nodes.remove(nd)
+      self.nodeids.pop(str(nd.id()))
+
+    node = None
+    if (ndtype == 'variable'):
+      node = opcua_node_variable_t(id, self)
+    elif (ndtype == 'object'):
+      node = opcua_node_object_t(id, self)
+    elif (ndtype == 'method'):
+      node = opcua_node_method_t(id, self)
+    elif (ndtype == 'objecttype'):
+      node = opcua_node_objectType_t(id, self)
+    elif (ndtype == 'variabletype'):
+      node = opcua_node_variableType_t(id, self)
+    elif (ndtype == 'methodtype'):
+      node = opcua_node_methodType_t(id, self)
+    elif (ndtype == 'datatype'):
+      node = opcua_node_dataType_t(id, self)
+    elif (ndtype == 'referencetype'):
+      node = opcua_node_referenceType_t(id, self)
+    else:
+      log(self,  "No node constructor for type " + ndtype, LOG_LEVEL_ERROR)
+
+    if node != None:
+      node.parseXML(xmlelement)
+
+    self.nodes.append(node)
+    self.nodeids[str(node.id())] = node
+
+  def removeNodeById(self, nodeId):
+    nd = self.getNodeByIDString(nodeId)
+    if nd == None:
+      return False
+
+    log(self, "Removing nodeId " + str(nodeId), LOG_LEVEL_DEBUG)
+    self.nodes.remove(nd)
+    if nd.getInverseReferences() != None:
+      for ref in nd.getInverseReferences():
+        src = ref.target();
+        src.removeReferenceToNode(nd)
+
+    return True
+
+  def registerBinaryIndirectPointer(self, node):
+    """ Appends a node to the list of nodes that should be contained in the
+        first 765 bytes (255 pointer slots a 3 bytes) in the binary
+        representation (indirect referencing space).
+
+        This function is reserved for references and dataType pointers.
+    """
+    if not node in self.__binaryIndirectPointers__:
+      self.__binaryIndirectPointers__.append(node)
+    return self.__binaryIndirectPointers__.index(node)
+
+  def getBinaryIndirectPointerIndex(self, node):
+    """ Returns the slot/index of a pointer in the indirect referencing space
+        (first 765 Bytes) of the binary representation.
+    """
+    if not node in self.__binaryIndirectPointers__:
+      return -1
+    return self.__binaryIndirectPointers__.index(node)
+
+
+  def parseXML(self, xmldoc):
+    """ Reads an XML Namespace definition and instantiates node.
+
+        No return value
+
+        parseXML open the file xmldoc using xml.dom.minidom and searches for
+        the first UANodeSet Element. For every Element encountered, createNode
+        is called to instantiate a node of the appropriate type.
+    """
+    typedict = {}
+    UANodeSet = dom.parse(xmldoc).getElementsByTagName("UANodeSet")
+    if len(UANodeSet) == 0:
+      log(self,  "Error: No NodeSets found", LOG_LEVEL_ERROR)
+      return
+    if len(UANodeSet) != 1:
+      log(self,  "Error: Found more than 1 Nodeset in XML File", LOG_LEVEL_ERROR)
+
+    UANodeSet = UANodeSet[0]
+    for nd in UANodeSet.childNodes:
+      if nd.nodeType != nd.ELEMENT_NODE:
+        continue
+
+      ndType = nd.tagName.lower()
+      if ndType[:2] == "ua":
+        ndType = ndType[2:]
+      elif not ndType in self.knownNodeTypes:
+        log(self, "XML Element or NodeType " + ndType + " is unknown and will be ignored", LOG_LEVEL_WARN)
+        continue
+
+      if not typedict.has_key(ndType):
+        typedict[ndType] = 1
+      else:
+        typedict[ndType] = typedict[ndType] + 1
+
+      self.createNode(ndType, nd)
+    log(self, "Currently " + str(len(self.nodes)) + " nodes in address space. Type distribution for this run was: " + str(typedict))
+
+  def linkOpenPointers(self):
+    """ Substitutes symbolic NodeIds in references for actual node instances.
+
+        No return value
+
+        References that have registered themselves with linkLater() to have
+        their symbolic NodeId targets ("ns=2; i=32") substited for an actual
+        node will be iterated by this function. For each reference encountered
+        in the list of unlinked/open references, the target string will be
+        evaluated and searched for in the node list of this namespace. If found,
+        the target attribute of the reference will be substituted for the
+        found node.
+
+        If a reference fails to get linked, it will remain in the list of
+        unlinked references. The individual items in this list can be
+        retrieved using getUnlinkedPointers().
+    """
+    linked = []
+
+    log(self,  str(self.unlinkedItemCount()) + " pointers need to get linked.")
+    for l in self.__linkLater__:
+      targetLinked = False
+      if not l.target() == None and not isinstance(l.target(), opcua_node_t):
+        if isinstance(l.target(),str) or isinstance(l.target(),unicode):
+          # If is not a node ID, it should be an alias. Try replacing it
+          # with a proper node ID
+          if l.target() in self.aliases:
+            l.target(self.aliases[l.target()])
+          # If the link is a node ID, try to find it hopening that no ass has
+          # defined more than one kind of id for that sucker
+          if l.target()[:2] == "i=" or l.target()[:2] == "g=" or \
+             l.target()[:2] == "b=" or l.target()[:2] == "s=" or \
+             l.target()[:3] == "ns=" :
+            tgt = self.getNodeByIDString(str(l.target()))
+            if tgt == None:
+              log(self, "Failed to link pointer to target (node not found) " + l.target(), LOG_LEVEL_ERROR)
+            else:
+              l.target(tgt)
+              targetLinked = True
+          else:
+            log(self, "Failed to link pointer to target (target not Alias or Node) " + l.target(), LOG_LEVEL_ERROR)
+        else:
+          log(self, "Failed to link pointer to target (don't know dummy type + " + str(type(l.target())) + " +) " + str(l.target()), LOG_LEVEL_ERROR)
+      else:
+        log(self, "Pointer has null target: " + str(l), LOG_LEVEL_ERROR)
+
+
+      referenceLinked = False
+      if not l.referenceType() == None:
+        if l.referenceType() in self.aliases:
+          l.referenceType(self.aliases[l.referenceType()])
+        if l.referenceType()[:2] == "i=" or l.referenceType()[:2] == "g=" or \
+           l.referenceType()[:2] == "b=" or l.referenceType()[:2] == "s=":
+          tgt = self.getNodeByIDString(str(l.referenceType()))
+          if tgt == None:
+            log(self, "Failed to link reference type to target (node not found) " + l.referenceType(), LOG_LEVEL_ERROR)
+          else:
+            l.referenceType(tgt)
+            referenceLinked = True
+      else:
+        referenceLinked = True
+
+      if referenceLinked == True and targetLinked == True:
+        linked.append(l)
+
+    # References marked as "not forward" must be inverted (removed from source node, assigned to target node and relinked)
+    log(self, "Inverting reference direction for all references with isForward==False attribute (is this correct!?)", LOG_LEVEL_WARN)
+    for n in self.nodes:
+      for r in n.getReferences():
+        if r.isForward() == False:
+          tgt = r.target()
+          if isinstance(tgt, opcua_node_t):
+            nref = opcua_referencePointer_t(n, parentNode=tgt)
+            nref.referenceType(r.referenceType())
+            tgt.addReference(nref)
+
+    # Create inverse references for all nodes
+    log(self, "Updating all referencedBy fields in nodes for inverse lookups.")
+    for n in self.nodes:
+      n.updateInverseReferences()
+
+    for l in linked:
+      self.__linkLater__.remove(l)
+
+    if len(self.__linkLater__) != 0:
+      log(self, str(len(self.__linkLater__)) + " could not be linked.", LOG_LEVEL_WARN)
+
+  def sanitize(self):
+    remove = []
+    log(self, "Sanitizing nodes and references...")
+    for n in self.nodes:
+      if n.sanitize() == False:
+        remove.append(n)
+    if not len(remove) == 0:
+      log(self, str(len(remove)) + " nodes will be removed because they failed sanitation.", LOG_LEVEL_WARN)
+    # FIXME: Some variable ns=0 nodes fail because they don't have DataType fields...
+    #        How should this be handles!?
+    log(self, "Not actually removing nodes... it's unclear if this is valid or not", LOG_LEVEL_WARN)
+
+  def getRoot(self):
+    """ Returns the first node instance with the browseName "Root".
+    """
+    return self.getNodeByBrowseName("Root")
+
+  def buildEncodingRules(self):
+    """ Calls buildEncoding() for all DataType nodes (opcua_node_dataType_t).
+
+        No return value
+    """
+    stat = {True: 0, False: 0}
+    for n in self.nodes:
+      if isinstance(n, opcua_node_dataType_t):
+        n.buildEncoding()
+        stat[n.isEncodable()] = stat[n.isEncodable()] + 1
+    log(self, "Type definitions built/passed: " +  str(stat), LOG_LEVEL_DEBUG)
+
+  def allocateVariables(self):
+    for n in self.nodes:
+      if isinstance(n, opcua_node_variable_t):
+        n.allocateValue()
+
+  def printDot(self, filename="namespace.dot"):
+    """ Outputs a graphiz/dot description of all nodes in the namespace.
+
+        Output will written into filename to be parsed by dot/neato...
+
+        Note that for namespaces with more then 20 nodes the reference structure
+        will lead to a mostly illegible and huge graph. Use printDotGraphWalk()
+        for plotting specific portions of a large namespace.
+    """
+    file=open(filename, 'w+')
+
+    file.write("digraph ns {\n")
+    for n in self.nodes:
+      file.write(n.printDot())
+    file.write("}\n")
+    file.close()
+
+  def printDotGraphWalk(self, depth=1, filename="out.dot", rootNode=None, followInverse = False, excludeNodeIds=[]):
+    """ Outputs a graphiz/dot description the nodes centered around rootNode.
+
+        References beginning from rootNode will be followed for depth steps. If
+        "followInverse = True" is passed, then inverse (not Forward) references
+        will also be followed.
+
+        Nodes can be excluded from the graph by passing a list of NodeIds as
+        string representation using excludeNodeIds (ex ["i=53", "ns=2;i=453"]).
+
+        Output is written into filename to be parsed by dot/neato/srfp...
+    """
+    iter = depth
+    processed = []
+    if rootNode == None or \
+       not isinstance(rootNode, opcua_node_t) or \
+       not rootNode in self.nodes:
+      root = self.getRoot()
+    else:
+      root = rootNode
+
+    file=open(filename, 'w+')
+
+    if root == None:
+      return
+
+    file.write("digraph ns {\n")
+    file.write(root.printDot())
+    refs=[]
+    if followInverse == True:
+      refs = root.getReferences(); # + root.getInverseReferences()
+    else:
+      for ref in root.getReferences():
+        if ref.isForward():
+          refs.append(ref)
+    while iter > 0:
+      tmp = []
+      for ref in refs:
+        if isinstance(ref.target(), opcua_node_t):
+          tgt = ref.target()
+          if not str(tgt.id()) in excludeNodeIds:
+            if not tgt in processed:
+              file.write(tgt.printDot())
+              processed.append(tgt)
+              if ref.isForward() == False and followInverse == True:
+                tmp = tmp + tgt.getReferences(); # + tgt.getInverseReferences()
+              elif ref.isForward() == True :
+                tmp = tmp + tgt.getReferences();
+      refs = tmp
+      iter = iter - 1
+
+    file.write("}\n")
+    file.close()
+
+  def printOpen62541Header(self, printedExternally=[], supressGenerationOfAttribute=[], outfilename=""):
+    unPrintedNodes = []
+    unPrintedRefs  = []
+    code = []
+    header = []
+
+    # Some macros (UA_EXPANDEDNODEID_MACRO()...) are easily created, but
+    # bulky. This class will help to offload some code.
+    codegen = open62541_MacroHelper(supressGenerationOfAttribute=supressGenerationOfAttribute)
+
+    # Populate the unPrinted-Lists with everything we have.
+    # Every Time a nodes printfunction is called, it will pop itself and
+    #   all printed references from these lists.
+    for n in self.nodes:
+      if not n in printedExternally:
+        unPrintedNodes.append(n)
+      else:
+        log(self, "Node " + str(n.id()) + " is being ignored.", LOG_LEVEL_DEBUG)
+    for n in unPrintedNodes:
+      for r in n.getReferences():
+        if (r.target() != None) and (r.target().id() != None) and (r.parent() != None):
+          unPrintedRefs.append(r)
+
+    log(self, str(len(unPrintedNodes)) + " Nodes, " + str(len(unPrintedRefs)) +  "References need to get printed.", LOG_LEVEL_DEBUG)
+    header.append("/* WARNING: This is a generated file.\n * Any manual changes will be overwritten.\n\n */")
+    code.append("/* WARNING: This is a generated file.\n * Any manual changes will be overwritten.\n\n */")
+
+    header.append("#ifndef "+outfilename.upper()+"_H_")
+    header.append("#define "+outfilename.upper()+"_H_")
+
+    header.append('#include "server/ua_server_internal.h"')
+    header.append('#include "server/ua_nodes.h"')
+    header.append('#include "ua_types.h"')
+    header.append("extern void "+outfilename+"(UA_Server *server);\n")
+    header.append("#endif /* "+outfilename.upper()+"_H_ */")
+
+    code.append('#include "'+outfilename+'.h"')
+    code.append("inline void "+outfilename+"(UA_Server *server) {")
+
+
+    # Find all references necessary to create the namespace and
+    # "Bootstrap" them so all other nodes can safely use these referencetypes whenever
+    # they can locate both source and target of the reference.
+    log(self, "Collecting all references used in the namespace.", LOG_LEVEL_DEBUG)
+    refsUsed = []
+    for n in self.nodes:
+      for r in n.getReferences():
+        if not r.referenceType() in refsUsed:
+          refsUsed.append(r.referenceType())
+    log(self, str(len(refsUsed)) + " reference types are used in the namespace, which will now get bootstrapped.", LOG_LEVEL_DEBUG)
+    for r in refsUsed:
+      code = code + r.printOpen62541CCode(unPrintedNodes, unPrintedRefs);
+
+    # Note to self: do NOT - NOT! - try to iterate over unPrintedNodes!
+    #               Nodes remove themselves from this list when printed.
+    log(self, "Printing all other nodes.", LOG_LEVEL_DEBUG)
+    for n in self.nodes:
+      code = code + n.printOpen62541CCode(unPrintedNodes, unPrintedRefs, supressGenerationOfAttribute=supressGenerationOfAttribute)
+
+    if len(unPrintedNodes) != 0:
+      log(self, "" + str(len(unPrintedNodes)) + " nodes could not be translated to code.", LOG_LEVEL_WARN)
+    else:
+      log(self, "Printing suceeded for all nodes", LOG_LEVEL_DEBUG)
+
+    if len(unPrintedRefs) != 0:
+      log(self, "Attempting to print " + str(len(unPrintedRefs)) + " unprinted references.", LOG_LEVEL_DEBUG)
+      tmprefs = []
+      for r in unPrintedRefs:
+        if  not (r.target() not in unPrintedNodes) and not (r.parent() in unPrintedNodes):
+          if not isinstance(r.parent(), opcua_node_t):
+            log(self, "Reference has no parent!", LOG_LEVEL_DEBUG)
+          elif not isinstance(r.parent().id(), opcua_node_id_t):
+            log(self, "Parents nodeid is not a nodeID!", LOG_LEVEL_DEBUG)
+          else:
+            if (len(tmprefs) == 0):
+              code.append("//  Creating leftover references:")
+            code = code + codegen.getCreateStandaloneReference(r.parent(), r)
+            code.append("")
+            tmprefs.append(r)
+      # Remove printed refs from list
+      for r in tmprefs:
+        unPrintedRefs.remove(r)
+      if len(unPrintedRefs) != 0:
+        log(self, "" + str(len(unPrintedRefs)) + " references could not be translated to code.", LOG_LEVEL_WARN)
+    else:
+      log(self, "Printing succeeded for all references", LOG_LEVEL_DEBUG)
+
+    code.append("}")
+    return (header,code)
+
+###
+### Testing
+###
+
+class testing:
+  def __init__(self):
+    self.namespace = opcua_namespace("testing")
+
+    log(self, "Phase 1: Reading XML file nodessets")
+    self.namespace.parseXML("Opc.Ua.NodeSet2.xml")
+    #self.namespace.parseXML("Opc.Ua.NodeSet2.Part4.xml")
+    #self.namespace.parseXML("Opc.Ua.NodeSet2.Part5.xml")
+    #self.namespace.parseXML("Opc.Ua.SimulationNodeSet2.xml")
+
+    log(self, "Phase 2: Linking address space references and datatypes")
+    self.namespace.linkOpenPointers()
+    self.namespace.sanitize()
+
+    log(self, "Phase 3: Comprehending DataType encoding rules")
+    self.namespace.buildEncodingRules()
+
+    log(self, "Phase 4: Allocating variable value data")
+    self.namespace.allocateVariables()
+
+    bin = self.namespace.buildBinary()
+    f = open("binary.base64","w+")
+    f.write(bin.encode("base64"))
+    f.close()
+
+    allnodes = self.namespace.nodes;
+    ns = [self.namespace.getRoot()]
+
+    i = 0
+    #print "Starting depth search on " + str(len(allnodes)) + " nodes starting with from " + str(ns)
+    while (len(ns) < len(allnodes)):
+      i = i + 1;
+      tmp = [];
+      print "Iteration: " + str(i)
+      for n in ns:
+        tmp.append(n)
+        for r in n.getReferences():
+          if (not r.target() in tmp):
+           tmp.append(r.target())
+      print "...tmp, " + str(len(tmp)) + " nodes discovered"
+      ns = []
+      for n in tmp:
+        ns.append(n)
+      print "...done, " + str(len(ns)) + " nodes discovered"
+
+    log(self, "Phase 5: Printing pretty graph")
+    self.namespace.printDotGraphWalk(depth=1, rootNode=self.namespace.getNodeByIDString("i=84"), followInverse=False, excludeNodeIds=["i=29", "i=22", "i=25"])
+    #self.namespace.printDot()
+
+class testing_open62541_header:
+  def __init__(self):
+    self.namespace = opcua_namespace("testing")
+
+    log(self, "Phase 1: Reading XML file nodessets")
+    self.namespace.parseXML("Opc.Ua.NodeSet2.xml")
+    #self.namespace.parseXML("Opc.Ua.NodeSet2.Part4.xml")
+    #self.namespace.parseXML("Opc.Ua.NodeSet2.Part5.xml")
+    #self.namespace.parseXML("Opc.Ua.SimulationNodeSet2.xml")
+
+    log(self, "Phase 2: Linking address space references and datatypes")
+    self.namespace.linkOpenPointers()
+    self.namespace.sanitize()
+
+    log(self, "Phase 3: Calling C Printers")
+    code = self.namespace.printOpen62541Header()
+
+    codeout = open("./open62541_namespace.c", "w+")
+    for line in code:
+      codeout.write(line + "\n")
+    codeout.close()
+    return
+
+# Call testing routine if invoked standalone.
+# For better debugging, it is advised to import this file using an interactive
+# python shell and instantiating a namespace.
+#
+# import ua_types.py as ua; ns=ua.testing().namespace
+if __name__ == '__main__':
+  tst = testing_open62541_header()

Diferenças do arquivo suprimidas por serem muito extensas
+ 1534 - 0
tools/pyUANamespace/ua_node_types.py


+ 823 - 0
tools/schema/namespace0/Opc.Ua.NodeSet2.Minimal.xml

@@ -0,0 +1,823 @@
+<?xml version="1.0" encoding="utf-8"?>
+<UANodeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.02" LastModified="2013-03-06T05:36:44.0862658Z" xmlns="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd">
+  <Aliases>
+    <Alias Alias="Boolean">i=1</Alias>
+    <Alias Alias="SByte">i=2</Alias>
+    <Alias Alias="Byte">i=3</Alias>
+    <Alias Alias="Int16">i=4</Alias>
+    <Alias Alias="UInt16">i=5</Alias>
+    <Alias Alias="Int32">i=6</Alias>
+    <Alias Alias="UInt32">i=7</Alias>
+    <Alias Alias="Int64">i=8</Alias>
+    <Alias Alias="UInt64">i=9</Alias>
+    <Alias Alias="Float">i=10</Alias>
+    <Alias Alias="Double">i=11</Alias>
+    <Alias Alias="DateTime">i=13</Alias>
+    <Alias Alias="String">i=12</Alias>
+    <Alias Alias="ByteString">i=15</Alias>
+    <Alias Alias="Guid">i=14</Alias>
+    <Alias Alias="XmlElement">i=16</Alias>
+    <Alias Alias="NodeId">i=17</Alias>
+    <Alias Alias="ExpandedNodeId">i=18</Alias>
+    <Alias Alias="QualifiedName">i=20</Alias>
+    <Alias Alias="LocalizedText">i=21</Alias>
+    <Alias Alias="StatusCode">i=19</Alias>
+    <Alias Alias="Structure">i=22</Alias>
+    <Alias Alias="Number">i=26</Alias>
+    <Alias Alias="Integer">i=27</Alias>
+    <Alias Alias="UInteger">i=28</Alias>
+    <Alias Alias="HasComponent">i=47</Alias>
+    <Alias Alias="HasProperty">i=46</Alias>
+    <Alias Alias="Organizes">i=35</Alias>
+    <Alias Alias="HasEventSource">i=36</Alias>
+    <Alias Alias="HasNotifier">i=48</Alias>
+    <Alias Alias="HasSubtype">i=45</Alias>
+    <Alias Alias="HasTypeDefinition">i=40</Alias>
+    <Alias Alias="HasModellingRule">i=37</Alias>
+    <Alias Alias="HasEncoding">i=38</Alias>
+    <Alias Alias="HasDescription">i=39</Alias>
+  </Aliases>
+  <UAReferenceType NodeId="i=31" BrowseName="References" IsAbstract="true" Symmetric="true">
+    <DisplayName>References</DisplayName>
+    <Description>The abstract base type for all references.</Description>
+    <References />
+    <InverseName>References</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=45" BrowseName="HasSubtype">
+    <DisplayName>HasSubtype</DisplayName>
+    <Description>The type for non-looping hierarchical references that are used to define sub types.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=34</Reference>
+    </References>
+    <InverseName>HasSupertype</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=33" BrowseName="HierarchicalReferences" IsAbstract="true">
+    <DisplayName>HierarchicalReferences</DisplayName>
+    <Description>The abstract base type for all hierarchical references.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=31</Reference>
+    </References>
+    <InverseName>HierarchicalReferences</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=32" BrowseName="NonHierarchicalReferences" IsAbstract="true">
+    <DisplayName>NonHierarchicalReferences</DisplayName>
+    <Description>The abstract base type for all non-hierarchical references.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=31</Reference>
+    </References>
+    <InverseName>NonHierarchicalReferences</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=34" BrowseName="HasChild">
+    <DisplayName>HasChild</DisplayName>
+    <Description>The abstract base type for all non-looping hierarchical references.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=33</Reference>
+    </References>
+    <InverseName>ChildOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=35" BrowseName="Organizes">
+    <DisplayName>Organizes</DisplayName>
+    <Description>The type for hierarchical references that are used to organize nodes.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=33</Reference>
+    </References>
+    <InverseName>OrganizedBy</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=36" BrowseName="HasEventSource">
+    <DisplayName>HasEventSource</DisplayName>
+    <Description>The type for non-looping hierarchical references that are used to organize event sources.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=33</Reference>
+    </References>
+    <InverseName>EventSourceOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=37" BrowseName="HasModellingRule">
+    <DisplayName>HasModellingRule</DisplayName>
+    <Description>The type for references from instance declarations to modelling rule nodes.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
+    </References>
+    <InverseName>ModellingRuleOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=38" BrowseName="HasEncoding">
+    <DisplayName>HasEncoding</DisplayName>
+    <Description>The type for references from data type nodes to to data type encoding nodes.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
+    </References>
+    <InverseName>EncodingOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=39" BrowseName="HasDescription">
+    <DisplayName>HasDescription</DisplayName>
+    <Description>The type for references from data type encoding nodes to data type description nodes.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
+    </References>
+    <InverseName>DescriptionOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=40" BrowseName="HasTypeDefinition">
+    <DisplayName>HasTypeDefinition</DisplayName>
+    <Description>The type for references from a instance node its type defintion node.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
+    </References>
+    <InverseName>TypeDefinitionOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=41" BrowseName="GeneratesEvent">
+    <DisplayName>GeneratesEvent</DisplayName>
+    <Description>The type for references from a node to an event type that is raised by node.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
+    </References>
+    <InverseName>GeneratesEvent</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=44" BrowseName="Aggregates">
+    <DisplayName>Aggregates</DisplayName>
+    <Description>The type for non-looping hierarchical references that are used to aggregate nodes into complex types.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=34</Reference>
+    </References>
+    <InverseName>AggregatedBy</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=46" BrowseName="HasProperty">
+    <DisplayName>HasProperty</DisplayName>
+    <Description>The type for non-looping hierarchical reference from a node to its property.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=44</Reference>
+    </References>
+    <InverseName>PropertyOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=47" BrowseName="HasComponent">
+    <DisplayName>HasComponent</DisplayName>
+    <Description>The type for non-looping hierarchical reference from a node to its component.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=44</Reference>
+    </References>
+    <InverseName>ComponentOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=48" BrowseName="HasNotifier">
+    <DisplayName>HasNotifier</DisplayName>
+    <Description>The type for non-looping hierarchical references that are used to indicate how events propagate from node to node.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=36</Reference>
+    </References>
+    <InverseName>NotifierOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=49" BrowseName="HasOrderedComponent">
+    <DisplayName>HasOrderedComponent</DisplayName>
+    <Description>The type for non-looping hierarchical reference from a node to its component when the order of references matters.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=47</Reference>
+    </References>
+    <InverseName>OrderedComponentOf</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=51" BrowseName="FromState">
+    <DisplayName>FromState</DisplayName>
+    <Description>The type for a reference to the state before a transition.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
+    </References>
+    <InverseName>ToTransition</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=52" BrowseName="ToState">
+    <DisplayName>ToState</DisplayName>
+    <Description>The type for a reference to the state after a transition.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
+    </References>
+    <InverseName>FromTransition</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=53" BrowseName="HasCause">
+    <DisplayName>HasCause</DisplayName>
+    <Description>The type for a reference to a method that can cause a transition to occur.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
+    </References>
+    <InverseName>MayBeCausedBy</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=54" BrowseName="HasEffect">
+    <DisplayName>HasEffect</DisplayName>
+    <Description>The type for a reference to an event that may be raised when a transition occurs.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
+    </References>
+    <InverseName>MayBeEffectedBy</InverseName>
+  </UAReferenceType>
+  <UAReferenceType NodeId="i=56" BrowseName="HasHistoricalConfiguration">
+    <DisplayName>HasHistoricalConfiguration</DisplayName>
+    <Description>The type for a reference to the historical configuration for a data variable.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=44</Reference>
+    </References>
+    <InverseName>HistoricalConfigurationOf</InverseName>
+  </UAReferenceType>
+  
+  <UAObject NodeId="i=84" BrowseName="Root" SymbolicName="RootFolder">
+    <DisplayName>Root</DisplayName>
+    <Description>The root of thä servör address späuce.</Description>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=61</Reference>
+    </References>
+  </UAObject>
+  <UAObject NodeId="i=85" BrowseName="Objects" SymbolicName="ObjectsFolder">
+    <DisplayName>Objects</DisplayName>
+    <Description>The browse entry point when looking for objects in the server address space.</Description>
+    <References>
+      <Reference ReferenceType="Organizes" IsForward="false">i=84</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=61</Reference>
+    </References>
+  </UAObject>
+  <UAObject NodeId="i=86" BrowseName="Types" SymbolicName="TypesFolder">
+    <DisplayName>Types</DisplayName>
+    <Description>The browse entry point when looking for types in the server address space.</Description>
+    <References>
+      <Reference ReferenceType="Organizes" IsForward="false">i=84</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=61</Reference>
+    </References>
+  </UAObject>
+  <UAObject NodeId="i=87" BrowseName="Views" SymbolicName="ViewsFolder">
+    <DisplayName>Views</DisplayName>
+    <Description>The browse entry point when looking for views in the server address space.</Description>
+    <References>
+      <Reference ReferenceType="Organizes" IsForward="false">i=84</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=61</Reference>
+    </References>
+  </UAObject>
+  <UAObject NodeId="i=91" BrowseName="ReferenceTypes" SymbolicName="ReferenceTypesFolder">
+    <DisplayName>ReferenceTypes</DisplayName>
+    <Description>The browse entry point when looking for reference types in the server address space.</Description>
+    <References>
+      <Reference ReferenceType="Organizes" IsForward="false">i=86</Reference>
+      <Reference ReferenceType="Organizes">i=31</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=61</Reference>
+    </References>
+  </UAObject>
+  <UAObjectType NodeId="i=58" BrowseName="BaseObjectType">
+    <DisplayName>BaseObjectType</DisplayName>
+    <Description>The base type for all object nodes.</Description>
+    <References />
+  </UAObjectType>
+  <UAObjectType NodeId="i=61" BrowseName="FolderType">
+    <DisplayName>FolderType</DisplayName>
+    <Description>The type for objects that organize other nodes.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=58</Reference>
+    </References>
+  </UAObjectType>
+  <UAObjectType NodeId="i=2004" BrowseName="ServerType">
+    <DisplayName>ServerType</DisplayName>
+    <Description>Specifies the current status and capabilities of the server.</Description>
+    <References>
+      <Reference ReferenceType="HasProperty">i=2005</Reference>
+      <Reference ReferenceType="HasProperty">i=2006</Reference>
+      <Reference ReferenceType="HasComponent">i=2007</Reference>
+      <Reference ReferenceType="HasProperty">i=2008</Reference>
+      <Reference ReferenceType="HasProperty">i=2742</Reference>
+      <Reference ReferenceType="HasComponent">i=2009</Reference>
+      <Reference ReferenceType="HasComponent">i=2010</Reference>
+      <Reference ReferenceType="HasComponent">i=2011</Reference>
+      <Reference ReferenceType="HasComponent">i=2012</Reference>
+      <Reference ReferenceType="HasComponent">i=11527</Reference>
+      <Reference ReferenceType="HasComponent">i=11489</Reference>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=58</Reference>
+    </References>
+  </UAObjectType>
+  <UAObjectType NodeId="i=2020" BrowseName="ServerDiagnosticsType">
+    <DisplayName>ServerDiagnosticsType</DisplayName>
+    <Description>The diagnostics information for a server.</Description>
+    <References>
+      <Reference ReferenceType="HasComponent">i=2021</Reference>
+      <Reference ReferenceType="HasComponent">i=2022</Reference>
+      <Reference ReferenceType="HasComponent">i=2023</Reference>
+      <Reference ReferenceType="HasComponent">i=2744</Reference>
+      <Reference ReferenceType="HasProperty">i=2025</Reference>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=58</Reference>
+    </References>
+  </UAObjectType>
+  <UAObjectType NodeId="i=2013" BrowseName="ServerCapabilitiesType">
+    <DisplayName>ServerCapabilitiesType</DisplayName>
+    <Description>Describes the capabilities supported by the server.</Description>
+    <References>
+      <Reference ReferenceType="HasProperty">i=2014</Reference>
+      <Reference ReferenceType="HasProperty">i=2016</Reference>
+      <Reference ReferenceType="HasProperty">i=2017</Reference>
+      <Reference ReferenceType="HasProperty">i=2732</Reference>
+      <Reference ReferenceType="HasProperty">i=2733</Reference>
+      <Reference ReferenceType="HasProperty">i=2734</Reference>
+      <Reference ReferenceType="HasProperty">i=3049</Reference>
+      <Reference ReferenceType="HasProperty">i=11549</Reference>
+      <Reference ReferenceType="HasProperty">i=11550</Reference>
+      <Reference ReferenceType="HasComponent">i=11551</Reference>
+      <Reference ReferenceType="HasComponent">i=2019</Reference>
+      <Reference ReferenceType="HasComponent">i=2754</Reference>
+      <Reference ReferenceType="HasComponent">i=11562</Reference>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=58</Reference>
+    </References>
+  </UAObjectType>
+  <UAVariableType NodeId="i=2138" BrowseName="ServerStatusType" DataType="i=862">
+    <DisplayName>ServerStatusType</DisplayName>
+    <References>
+      <Reference ReferenceType="HasComponent">i=2139</Reference>
+      <Reference ReferenceType="HasComponent">i=2140</Reference>
+      <Reference ReferenceType="HasComponent">i=2141</Reference>
+      <Reference ReferenceType="HasComponent">i=2142</Reference>
+      <Reference ReferenceType="HasComponent">i=2752</Reference>
+      <Reference ReferenceType="HasComponent">i=2753</Reference>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=63</Reference>
+    </References>
+  </UAVariableType>
+  <UAVariableType NodeId="i=3051" BrowseName="BuildInfoType" DataType="i=338">
+    <DisplayName>BuildInfoType</DisplayName>
+    <References>
+      <Reference ReferenceType="HasComponent">i=3052</Reference>
+      <Reference ReferenceType="HasComponent">i=3053</Reference>
+      <Reference ReferenceType="HasComponent">i=3054</Reference>
+      <Reference ReferenceType="HasComponent">i=3055</Reference>
+      <Reference ReferenceType="HasComponent">i=3056</Reference>
+      <Reference ReferenceType="HasComponent">i=3057</Reference>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=63</Reference>
+    </References>
+  </UAVariableType>
+  
+  
+  <UAObject NodeId="i=90" BrowseName="DataTypes" SymbolicName="DataTypesFolder">
+    <DisplayName>DataTypes</DisplayName>
+    <Description>The browse entry point when looking for data types in the server address space.</Description>
+    <References>
+      <Reference ReferenceType="Organizes" IsForward="false">i=86</Reference>
+      <Reference ReferenceType="Organizes">i=24</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=61</Reference>
+    </References>
+  </UAObject>
+  <UADataType NodeId="i=24" BrowseName="BaseDataType" IsAbstract="true">
+    <DisplayName>BaseDataType</DisplayName>
+    <Description>Describes a value that can have any valid DataType.</Description>
+    <References />
+  </UADataType>
+  <UADataType NodeId="i=1" BrowseName="Boolean">
+    <DisplayName>Boolean</DisplayName>
+    <Description>Describes a value that is either TRUE or FALSE.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=26" BrowseName="Number" IsAbstract="true">
+    <DisplayName>Number</DisplayName>
+    <Description>Describes a value that can have any numeric DataType.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=10" BrowseName="Float">
+    <DisplayName>Float</DisplayName>
+    <Description>Describes a value that is an IEEE 754-1985 single precision floating point number.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=26</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=11" BrowseName="Double">
+    <DisplayName>Double</DisplayName>
+    <Description>Describes a value that is an IEEE 754-1985 double precision floating point number.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=26</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=27" BrowseName="Integer" IsAbstract="true">
+    <DisplayName>Integer</DisplayName>
+    <Description>Describes a value that can have any integer DataType.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=26</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=2" BrowseName="SByte">
+    <DisplayName>SByte</DisplayName>
+    <Description>Describes a value that is an integer between -128 and 127.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=27</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=4" BrowseName="Int16">
+    <DisplayName>Int16</DisplayName>
+    <Description>Describes a value that is an integer between −32,768 and 32,767.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=27</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=6" BrowseName="Int32">
+    <DisplayName>Int32</DisplayName>
+    <Description>Describes a value that is an integer between −2,147,483,648  and 2,147,483,647.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=27</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=8" BrowseName="Int64">
+    <DisplayName>Int64</DisplayName>
+    <Description>Describes a value that is an integer between −9,223,372,036,854,775,808 and 9,223,372,036,854,775,807.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=27</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=28" BrowseName="UInteger" IsAbstract="true">
+    <DisplayName>UInteger</DisplayName>
+    <Description>Describes a value that can have any unsigned integer DataType.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=27</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=3" BrowseName="Byte">
+    <DisplayName>Byte</DisplayName>
+    <Description>Describes a value that is an integer between 0 and 255.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=28</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=5" BrowseName="UInt16">
+    <DisplayName>UInt16</DisplayName>
+    <Description>Describes a value that is an integer between 0 and 65535.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=28</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=7" BrowseName="UInt32">
+    <DisplayName>UInt32</DisplayName>
+    <Description>Describes a value that is an integer between 0 and 4,294,967,295.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=28</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=9" BrowseName="UInt64">
+    <DisplayName>UInt64</DisplayName>
+    <Description>Describes a value that is an integer between 0 and 18,446,744,073,709,551,615.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=28</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=12" BrowseName="String">
+    <DisplayName>String</DisplayName>
+    <Description>Describes a value that is a sequence of printable Unicode characters.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=13" BrowseName="DateTime">
+    <DisplayName>DateTime</DisplayName>
+    <Description>Describes a value that is a Gregorian calender date and time.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=14" BrowseName="Guid">
+    <DisplayName>Guid</DisplayName>
+    <Description>Describes a value that is a 128-bit globally unique identifier.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=15" BrowseName="ByteString">
+    <DisplayName>ByteString</DisplayName>
+    <Description>Describes a value that is a sequence of bytes.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=16" BrowseName="XmlElement">
+    <DisplayName>XmlElement</DisplayName>
+    <Description>Describes a value that is an XML element.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=17" BrowseName="NodeId">
+    <DisplayName>NodeId</DisplayName>
+    <Description>Describes a value that is an identifier for a node within a Server address space.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=18" BrowseName="ExpandedNodeId">
+    <DisplayName>ExpandedNodeId</DisplayName>
+    <Description>Describes a value that is an absolute identifier for a node.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=19" BrowseName="StatusCode">
+    <DisplayName>StatusCode</DisplayName>
+    <Description>Describes a value that is a code representing the outcome of an operation by a Server.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=20" BrowseName="QualifiedName">
+    <DisplayName>QualifiedName</DisplayName>
+    <Description>Describes a value that is a name qualified by a namespace.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=21" BrowseName="LocalizedText">
+    <DisplayName>LocalizedText</DisplayName>
+    <Description>Describes a value that is human readable Unicode text with a locale identifier.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=22" BrowseName="Structure" IsAbstract="true">
+    <DisplayName>Structure</DisplayName>
+    <Description>Describes a value that is any type of structure that can be described with a data encoding.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=862" BrowseName="ServerStatusDataType">
+    <DisplayName>ServerStatusDataType</DisplayName>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=22</Reference>
+    </References>
+    <Definition Name="ServerStatusDataType">
+      <Field Name="StartTime" DataType="i=294" />
+      <Field Name="CurrentTime" DataType="i=294" />
+      <Field Name="State" DataType="i=852" />
+      <Field Name="BuildInfo" DataType="i=338" />
+      <Field Name="SecondsTillShutdown" DataType="i=7" />
+      <Field Name="ShutdownReason" DataType="i=21" />
+    </Definition>
+  </UADataType>
+  <UADataType NodeId="i=338" BrowseName="BuildInfo">
+    <DisplayName>BuildInfo</DisplayName>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=22</Reference>
+    </References>
+    <Definition Name="BuildInfo">
+      <Field Name="ProductUri" DataType="i=12" />
+      <Field Name="ManufacturerName" DataType="i=12" />
+      <Field Name="ProductName" DataType="i=12" />
+      <Field Name="SoftwareVersion" DataType="i=12" />
+      <Field Name="BuildNumber" DataType="i=12" />
+      <Field Name="BuildDate" DataType="i=294" />
+    </Definition>
+  </UADataType>
+  <UADataType NodeId="i=23" BrowseName="DataValue">
+    <DisplayName>DataValue</DisplayName>
+    <Description>Describes a value that is a structure containing a value, a status code and timestamps.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=25" BrowseName="DiagnosticInfo">
+    <DisplayName>DiagnosticInfo</DisplayName>
+    <Description>Describes a value that is a structure containing diagnostics associated with a StatusCode.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=29" BrowseName="Enumeration" IsAbstract="true">
+    <DisplayName>Enumeration</DisplayName>
+    <Description>Describes a value that is an enumerated DataType.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=24</Reference>
+    </References>
+  </UADataType>
+  <UADataType NodeId="i=852" BrowseName="ServerState">
+    <DisplayName>ServerState</DisplayName>
+    <References>
+      <Reference ReferenceType="HasProperty">i=7612</Reference>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=29</Reference>
+    </References>
+    <Definition Name="ServerState">
+      <Field Name="Running" Value="0" />
+      <Field Name="Failed" Value="1" />
+      <Field Name="NoConfiguration" Value="2" />
+      <Field Name="Suspended" Value="3" />
+      <Field Name="Shutdown" Value="4" />
+      <Field Name="Test" Value="5" />
+      <Field Name="CommunicationFault" Value="6" />
+      <Field Name="Unknown" Value="7" />
+    </Definition>
+  </UADataType>
+  <UAObject NodeId="i=89" BrowseName="VariableTypes" SymbolicName="VariableTypesFolder">
+    <DisplayName>VariableTypes</DisplayName>
+    <Description>The browse entry point when looking for variable types in the server address space.</Description>
+    <References>
+      <Reference ReferenceType="Organizes" IsForward="false">i=86</Reference>
+      <Reference ReferenceType="Organizes">i=62</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=61</Reference>
+    </References>
+  </UAObject>
+  <UAVariableType NodeId="i=62" BrowseName="BaseVariableType" IsAbstract="true" ValueRank="-2">
+    <DisplayName>BaseVariableType</DisplayName>
+    <Description>The abstract base type for all variable nodes.</Description>
+    <References />
+  </UAVariableType>
+  <UAVariableType NodeId="i=63" BrowseName="BaseDataVariableType" ValueRank="-2">
+    <DisplayName>BaseDataVariableType</DisplayName>
+    <Description>The type for variable that represents a process value.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=62</Reference>
+    </References>
+  </UAVariableType>
+  <UAVariableType NodeId="i=68" BrowseName="PropertyType" ValueRank="-2">
+    <DisplayName>PropertyType</DisplayName>
+    <Description>The type for variable that represents a property of another node.</Description>
+    <References>
+      <Reference ReferenceType="HasSubtype" IsForward="false">i=62</Reference>
+    </References>
+  </UAVariableType>
+  
+  
+  <UAObject NodeId="i=2253" BrowseName="Server" EventNotifier="1">
+    <DisplayName>Server</DisplayName>
+    <References>
+      <Reference ReferenceType="HasProperty">i=2254</Reference>
+      <Reference ReferenceType="HasProperty">i=2255</Reference>
+      <Reference ReferenceType="HasComponent">i=2256</Reference>
+      <Reference ReferenceType="HasProperty">i=2267</Reference>
+      <Reference ReferenceType="HasProperty">i=2994</Reference>
+      <Reference ReferenceType="HasComponent">i=2268</Reference>
+      <Reference ReferenceType="HasComponent">i=2274</Reference>
+      <Reference ReferenceType="HasComponent">i=2295</Reference>
+      <Reference ReferenceType="HasComponent">i=2296</Reference>
+      <Reference ReferenceType="HasComponent">i=11715</Reference>
+      <Reference ReferenceType="HasComponent">i=11492</Reference>
+      <Reference ReferenceType="Organizes" IsForward="false">i=85</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=2004</Reference>
+    </References>
+  </UAObject>
+  <UAVariable NodeId="i=2255" BrowseName="NamespaceArray" ParentNodeId="i=2253" DataType="String" ValueRank="1" MinimumSamplingInterval="1000">
+    <DisplayName>NamespaceArray</DisplayName>
+    <Description>The list of namespace URIs used by the server.</Description>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=68</Reference>
+      <Reference ReferenceType="HasProperty" IsForward="false">i=2253</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2254" BrowseName="ServerArray" ParentNodeId="i=2253" DataType="String" ValueRank="1" MinimumSamplingInterval="1000">
+    <DisplayName>ServerArray</DisplayName>
+    <Description>The list of server URIs used by the server.</Description>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=68</Reference>
+      <Reference ReferenceType="HasProperty" IsForward="false">i=2253</Reference>
+    </References>
+  </UAVariable>
+  <UAObject NodeId="i=2268" BrowseName="ServerCapabilities" ParentNodeId="i=2253">
+    <DisplayName>ServerCapabilities</DisplayName>
+    <Description>Describes capabilities supported by the server.</Description>
+    <References>
+      <Reference ReferenceType="HasProperty">i=2269</Reference>
+      <Reference ReferenceType="HasProperty">i=2271</Reference>
+      <Reference ReferenceType="HasProperty">i=2272</Reference>
+      <Reference ReferenceType="HasProperty">i=2735</Reference>
+      <Reference ReferenceType="HasProperty">i=2736</Reference>
+      <Reference ReferenceType="HasProperty">i=2737</Reference>
+      <Reference ReferenceType="HasProperty">i=3704</Reference>
+      <Reference ReferenceType="HasProperty">i=11702</Reference>
+      <Reference ReferenceType="HasProperty">i=11703</Reference>
+      <Reference ReferenceType="HasComponent">i=11704</Reference>
+      <Reference ReferenceType="HasComponent">i=2996</Reference>
+      <Reference ReferenceType="HasComponent">i=2997</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=2013</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2253</Reference>
+    </References>
+  </UAObject>
+  <UAVariable NodeId="i=2271" BrowseName="LocaleIdArray" ParentNodeId="i=2268" DataType="i=295" ValueRank="1">
+    <DisplayName>LocaleIdArray</DisplayName>
+    <Description>A list of locales supported by the server.</Description>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=68</Reference>
+      <Reference ReferenceType="HasProperty" IsForward="false">i=2268</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2735" BrowseName="MaxBrowseContinuationPoints" ParentNodeId="i=2268" DataType="UInt16">
+    <DisplayName>MaxBrowseContinuationPoints</DisplayName>
+    <Description>The maximum number of continuation points for Browse operations per session.</Description>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=68</Reference>
+      <Reference ReferenceType="HasProperty" IsForward="false">i=2268</Reference>
+    </References>
+  </UAVariable>
+  <UAObject NodeId="i=2274" BrowseName="ServerDiagnostics" ParentNodeId="i=2253">
+    <DisplayName>ServerDiagnostics</DisplayName>
+    <Description>Reports diagnostics about the server.</Description>
+    <References>
+      <Reference ReferenceType="HasComponent">i=2275</Reference>
+      <Reference ReferenceType="HasComponent">i=2289</Reference>
+      <Reference ReferenceType="HasComponent">i=2290</Reference>
+      <Reference ReferenceType="HasComponent">i=3706</Reference>
+      <Reference ReferenceType="HasProperty">i=2294</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=2020</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2253</Reference>
+    </References>
+  </UAObject>
+  <UAVariable NodeId="i=2294" BrowseName="EnabledFlag" ParentNodeId="i=2274" DataType="Boolean" AccessLevel="3" UserAccessLevel="3">
+    <DisplayName>EnabledFlag</DisplayName>
+    <Description>If TRUE the diagnostics collection is enabled.</Description>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=68</Reference>
+      <Reference ReferenceType="HasProperty" IsForward="false">i=2274</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2256" BrowseName="ServerStatus" ParentNodeId="i=2253" DataType="i=862" MinimumSamplingInterval="1000">
+    <DisplayName>ServerStatus</DisplayName>
+    <Description>The current status of the server.</Description>
+    <References>
+      <Reference ReferenceType="HasComponent">i=2257</Reference>
+      <Reference ReferenceType="HasComponent">i=2258</Reference>
+      <Reference ReferenceType="HasComponent">i=2259</Reference>
+      <Reference ReferenceType="HasComponent">i=2260</Reference>
+      <Reference ReferenceType="HasComponent">i=2992</Reference>
+      <Reference ReferenceType="HasComponent">i=2993</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=2138</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2253</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2257" BrowseName="StartTime" ParentNodeId="i=2256" DataType="i=294">
+    <DisplayName>StartTime</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2256</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2258" BrowseName="CurrentTime" ParentNodeId="i=2256" DataType="i=294">
+    <DisplayName>CurrentTime</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2256</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2259" BrowseName="State" ParentNodeId="i=2256" DataType="i=852">
+    <DisplayName>State</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2256</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2260" BrowseName="BuildInfo" ParentNodeId="i=2256" DataType="i=338">
+    <DisplayName>BuildInfo</DisplayName>
+    <References>
+      <Reference ReferenceType="HasComponent">i=2262</Reference>
+      <Reference ReferenceType="HasComponent">i=2263</Reference>
+      <Reference ReferenceType="HasComponent">i=2261</Reference>
+      <Reference ReferenceType="HasComponent">i=2264</Reference>
+      <Reference ReferenceType="HasComponent">i=2265</Reference>
+      <Reference ReferenceType="HasComponent">i=2266</Reference>
+      <Reference ReferenceType="HasTypeDefinition">i=3051</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2256</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2262" BrowseName="ProductUri" ParentNodeId="i=2260" DataType="String" MinimumSamplingInterval="1000">
+    <DisplayName>ProductUri</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2260</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2263" BrowseName="ManufacturerName" ParentNodeId="i=2260" DataType="String" MinimumSamplingInterval="1000">
+    <DisplayName>ManufacturerName</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2260</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2261" BrowseName="ProductName" ParentNodeId="i=2260" DataType="String" MinimumSamplingInterval="1000">
+    <DisplayName>ProductName</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2260</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2264" BrowseName="SoftwareVersion" ParentNodeId="i=2260" DataType="String" MinimumSamplingInterval="1000">
+    <DisplayName>SoftwareVersion</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2260</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2265" BrowseName="BuildNumber" ParentNodeId="i=2260" DataType="String" MinimumSamplingInterval="1000">
+    <DisplayName>BuildNumber</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2260</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2266" BrowseName="BuildDate" ParentNodeId="i=2260" DataType="i=294" MinimumSamplingInterval="1000">
+    <DisplayName>BuildDate</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2260</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2992" BrowseName="SecondsTillShutdown" ParentNodeId="i=2256" DataType="UInt32">
+    <DisplayName>SecondsTillShutdown</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2256</Reference>
+    </References>
+  </UAVariable>
+  <UAVariable NodeId="i=2993" BrowseName="ShutdownReason" ParentNodeId="i=2256" DataType="LocalizedText">
+    <DisplayName>ShutdownReason</DisplayName>
+    <References>
+      <Reference ReferenceType="HasTypeDefinition">i=63</Reference>
+      <Reference ReferenceType="HasComponent" IsForward="false">i=2256</Reference>
+    </References>
+  </UAVariable>
+</UANodeSet>

Diferenças do arquivo suprimidas por serem muito extensas
+ 23008 - 0
tools/schema/namespace0/Opc.Ua.NodeSet2.xml


+ 3 - 0
tools/schema/namespace0/README.md

@@ -0,0 +1,3 @@
+This directory contains XML nodesets of namespace 0 for automatic generation.
+The generation option can be activated via CMake option ENABLE_GENERATE_NAMESPACE0.
+The nodesets can be selected via CMake variable GENERATE_NAMESPACE0_FILE.