Przeglądaj źródła

Squashed commit of the following:

commit e39b2f78a2da905034212ae35212422d00046168
Merge: a6ff58e d655a9f
Author: Stasik0 <github@stasik.com>
Date:   Sun Jun 7 12:57:50 2015 +0200

    Merge remote-tracking branch 'origin/master' into generated_ns0

    Conflicts:
    	src/server/ua_server.c

    merge and ajust namespapce generator

commit a6ff58e74b5f5bb8f62a3268d5e69029740bbc63
Author: Stasik0 <github@stasik.com>
Date:   Sun Jun 7 09:32:50 2015 +0200

    fixing typo

commit 071f6e2e7f983613447a7d3f33e3e270b40441b6
Merge: 7f38b29 dd14dee
Author: Stasik0 <github@stasik.com>
Date:   Sun Jun 7 09:29:50 2015 +0200

    Merge remote-tracking branch 'origin/master' into generated_ns0

commit 7f38b29003b7cc05db7bb946a06ec3f91a09f6e8
Author: Stasik0 <github@stasik.com>
Date:   Sun Jun 7 09:29:15 2015 +0200

    moved nodeset XML files to tools/schema/namespace0/

commit 663e6c26c2c04fcabd9b8ef59d4fcf4f74d4c2bf
Author: Stasik0 <github@stasik.com>
Date:   Sat Jun 6 22:59:51 2015 +0200

    merge-candidate (MC1) of the generate namespace feature
    @ichrispa: i changed the inline/extern jiu-jitsu, is it okay for you?

commit 3553ca6cc0530eb7387adbe3ae5794ca71e3b515
Author: Stasik0 <github@stasik.com>
Date:   Sat Jun 6 21:15:51 2015 +0200

    static function version

commit b5b5908e69da6746c4413b946958dcf3a8bc05a9
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 23:42:20 2015 +0200

    Generation of separate header/code enabled.

commit 6fc3dc58cbe67fba734629a166999ec0211373e7
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 23:41:59 2015 +0200

    Code generation now returns separate header/code data, using the outfilename as a function name.

commit da85fb5684ee5bf7c532868cd336e92e5a08a7b9
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 23:41:16 2015 +0200

    Using the generated namespace now includes a header and uses an inlined function call to cleanly separate function and definitions in generated source code.

commit e56f275acb617f1dd3475be43ef700771cc01e73
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 23:40:17 2015 +0200

    added -fgnu89-inline to make inlining of function with header/code file separation possible.

commit 2a419ec9ad5b3abd5c117c356959c29a12f60fdc
Author: Stasik0 <github@stasik.com>
Date:   Fri Jun 5 22:23:27 2015 +0200

    parsing minimal ns0 for default

commit 0f973a2b78f1ccd3343ab1fa58061237ce09eeb1
Author: Stasik0 <github@stasik.com>
Date:   Fri Jun 5 22:20:46 2015 +0200

    first try of bootstraping the minimal ns0

commit 4c7b6f43a07fa1f5a81ddc9d9220bb7ec70fa135
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 22:16:24 2015 +0200

    Removed duplicate inverseName generation

commit 72ce78a77ace3e1796353964498ed4b41ddd04e2
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 22:06:38 2015 +0200

    That already is a pointer.

commit dc69cebcc87e1227dc490b5b6632f104fbf2b3a4
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 22:04:17 2015 +0200

    Added standard initializer for nodes; removed manual init-to-default to reduce code footprint.

commit 1a3511701f155b50a5cc76fa1ac0223df1b77a94
Author: Stasik0 <github@stasik.com>
Date:   Fri Jun 5 20:18:38 2015 +0200

    moved to master

    Revert "minor correction for cumulative statuscode masking in UA_Array_copy as requested by vincent morrell (irc)."

    This reverts commit a5ffc683ab98fd8868ed15853bcb47a4a49ba41d.

commit 584f789baa72224015dd0b8e33f73109a3d3c7b3
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 19:02:56 2015 +0200

    added some basic documentation

commit 3d9e240a7ffe9613bf47fda7fa3196dda3541a29
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 18:06:37 2015 +0200

    Node_t base type passes supressed attribute to helper calls. Variable nodes now not only check the validity of their dataType pointer, they invalidate it during sanitation if necessary.

commit ce70a77bba3353220cb41cbbde7c415ac20bc370
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 18:05:18 2015 +0200

    Passes ignored attributes to all helper calls.

commit 4a5ca97a4f5961d8899a59b6b61acb5acdbe6c7f
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 18:04:52 2015 +0200

    Active suppression of node attribute generation. If suppression is not possible, they will be initialized to sensible defaults (null pointers, zero)

commit 51353df2dad03ce8b614534f48cee2771ae5fbb8
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 18:04:08 2015 +0200

    Added the ability to specify suppressable node attributes (-s <attribute> or --supress <attribute> in the command line).

commit a5ffc683ab98fd8868ed15853bcb47a4a49ba41d
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Fri Jun 5 18:02:27 2015 +0200

    minor correction for cumulative statuscode masking in UA_Array_copy as requested by vincent morrell (irc).

commit ef477f93060f490f2a583fd0109c3f5bc834747a
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Wed Jun 3 11:35:00 2015 +0200

    CMake now uses black/ignorelists in tools/pyUANamespace by default.

commit 5d5f2d11af9c3fc13ac90ac274abd5c556a27be6
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Wed Jun 3 11:31:05 2015 +0200

    Default ignore- and blacklists added.

commit 05fcccfbfa848a84e78c778e5f1036aa5252d48a
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Wed Jun 3 11:30:29 2015 +0200

    Added Ignorelist, Blacklist and Overwrite feature

commit a25b60d469c6fe5db94a8a69c9b6f9c85905e5bc
Author: Stasik0 <github@stasik.com>
Date:   Tue Jun 2 17:19:53 2015 +0200

    the generated namespace0 overlays the existing one

commit 269a14256e07ef385c5bf3147e97e0a5fad5c1f5
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Tue Jun 2 13:04:33 2015 +0200

    Adjusted pointer type for server_addnode generates.

commit 55cfb3887d9d7da6ebc95555a311325fe4852954
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Tue Jun 2 13:02:59 2015 +0200

    Readded -DLOADGENERATEDNS switch

commit 179f2a154ed48a9828f9b35e9f3e7ec18c12123a
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Tue Jun 2 13:02:35 2015 +0200

    including generated nodeset

commit c35db3ba91943be29101f55ae1dd8ee430e628e2
Author: ichrispa <Chris_Paul.Iatrou@tu-dresden.de>
Date:   Tue Jun 2 13:00:39 2015 +0200

    reenabled namespace generator support
ichrispa 9 lat temu
rodzic
commit
8e5fa53a02

+ 25 - 3
CMakeLists.txt

@@ -83,9 +83,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
@@ -123,6 +123,28 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids.h
                    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 ${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_SOURCE_DIR}/src_generated/ua_namespaceinit_generated.c)
+endif()
+
 ## logging
 set(UA_LOGLEVEL 300 CACHE STRING "Level at which logs shall be reported")
 

+ 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");
@@ -809,6 +813,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 */

+ 11 - 0
tools/pyUANamespace/NodeID_AssumeExternal.txt

@@ -0,0 +1,11 @@
+i=2254
+i=2255
+i=2256
+i=2267
+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

+ 133 - 0
tools/pyUANamespace/open62541_MacroHelper.py

@@ -0,0 +1,133 @@
+#!/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 = []
+    if reference.isForward():
+      code.append("UA_Server_addReference(server, " + self.getCreateNodeIDMacro(sourcenode) + ", " + self.getCreateNodeIDMacro(reference.referenceType()) + ", "+self.getCreateExpandedNodeIDMacro(reference.target())+");")
+    else:
+      code.append("UA_Server_addReference(server, " + self.getCreateNodeIDMacro(reference.target()) + ", " + self.getCreateNodeIDMacro(reference.referenceType()) + ", "+self.getCreateExpandedNodeIDMacro(sourcenode)+");")
+    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

Plik diff jest za duży
+ 1082 - 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()

Plik diff jest za duży
+ 1493 - 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>

Plik diff jest za duży
+ 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.