Kaynağa Gözat

Add options to bootstrap ns0: minimal, reduced and full

The option "minimal" does not use the nodeset compiler.
Julius Pfrommer 6 yıl önce
ebeveyn
işleme
befb0171d9

+ 19 - 11
CMakeLists.txt

@@ -64,9 +64,24 @@ option(UA_ENABLE_COVERAGE "Enable gcov coverage" OFF)
 option(UA_ENABLE_ENCRYPTION "Enable encryption support (uses mbedTLS)" OFF)
 option(BUILD_SHARED_LIBS "Enable building of shared libraries (dll/so)" OFF)
 
+# Namespace Zero
+set(UA_NAMESPACE_ZERO "REDUCED" CACHE STRING "Completeness of the generated namespace zero (minimal/reduced/full)")
+SET_PROPERTY(CACHE UA_NAMESPACE_ZERO PROPERTY STRINGS "MINIMAL" "REDUCED" "FULL")
+if(UA_NAMESPACE_ZERO STREQUAL "MINIMAL")
+    set(UA_GENERATED_NAMESPACE_ZERO OFF)
+else()
+    set(UA_GENERATED_NAMESPACE_ZERO ON)
+endif()
+
+if(MSVC AND UA_NAMESPACE_ZERO STREQUAL "FULL")
+    # For the full NS0 we need a stack size of 8MB (as it is default on linux)
+    # See https://github.com/open62541/open62541/issues/1326
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8000000")
+endif()
+
 # It should not be possible to enable events without enabling subscriptions and full ns0
-if ((UA_ENABLE_SUBSCRIPTIONS_EVENTS) AND (NOT (UA_ENABLE_SUBSCRIPTIONS AND UA_ENABLE_FULL_NS0)))
-    message(FATAL_ERROR "Unable to enable events without UA_ENABLE_SUBSCRIPTIONS and UA_ENABLE_FULL_NS0")
+if((UA_ENABLE_SUBSCRIPTIONS_EVENTS) AND (NOT (UA_ENABLE_SUBSCRIPTIONS AND UA_NAMESPACE_ZERO STREQUAL "FULL")))
+    message(FATAL_ERROR "Unable to enable events without UA_ENABLE_SUBSCRIPTIONS and full namespace 0")
 endif()
 
 if(UA_ENABLE_COVERAGE)
@@ -125,14 +140,7 @@ mark_as_advanced(UA_ENABLE_VALGRIND_INTERACTIVE)
 option(UA_MSVC_FORCE_STATIC_CRT "Force linking with the static C-runtime library when compiling to static library with MSVC" ON)
 mark_as_advanced(UA_MSVC_FORCE_STATIC_CRT)
 
-option(UA_ENABLE_FULL_NS0 "Use the full NS0 instead of a minimal Namespace 0 nodeset" OFF)
-if (MSVC AND UA_ENABLE_FULL_NS0)
-    # For the full NS0 we need a stack size of 8MB (as it is default on linux)
-    # See https://github.com/open62541/open62541/issues/1326
-    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8000000")
-endif()
-
-option(UA_FILE_NS0 "Custom NodeSet file containing NS0")
+option(UA_FILE_NS0 "Override the NodeSet xml file used to generate namespace zero")
 mark_as_advanced(UA_FILE_NS0)
 
 # Semaphores/file system may not be available on embedded devices. It can be
@@ -526,7 +534,7 @@ endif()
 # Generate source files #
 #########################
 
-if (UA_ENABLE_FULL_NS0)
+if(UA_NAMESPACE_ZERO STREQUAL "FULL")
     if(NOT UA_FILE_NS0)
         set(UA_FILE_NS0 ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/Schema/Opc.Ua.NodeSet2.xml)
     endif()

+ 66 - 29
doc/building.rst

@@ -132,8 +132,8 @@ Most options can be changed manually in :file:`ua_config.h` (:file:`open62541.h`
 for the single-file release) after the code generation. But usually there is no
 need to adjust them.
 
-Build Type and Logging
-^^^^^^^^^^^^^^^^^^^^^^
+Main Build Options
+^^^^^^^^^^^^^^^^^^
 
 **CMAKE_BUILD_TYPE**
   - ``RelWithDebInfo`` -O2 optimization with debug symbols
@@ -152,62 +152,81 @@ Build Type and Logging
      - 200: Debug
      - 100: Trace
 
-UA_BUILD_* group
-^^^^^^^^^^^^^^^^
+Select build artefacts
+^^^^^^^^^^^^^^^^^^^^^^
 
-By default only the shared object libopen62541.so or the library open62541.dll
-and open62541.dll.a resp. open62541.lib are build. Additional artifacts can be
-specified by the following options:
+By default only the main library shared object libopen62541.so (open62541.dll)
+or static linking archive open62541.a (open62541.lib) is built. Additional
+artifacts can be specified by the following options:
 
 **UA_BUILD_EXAMPLES**
-   Compile example servers and clients from :file:`examples/{xyz}.c`. A static and a dynamic binary is linked, respectively.
+   Compile example servers and clients from :file:`examples/*.c`.
 
 **UA_BUILD_UNIT_TESTS**
-   Compile unit tests with Check framework. The tests can be executed with ``make test``
-
-**UA_BUILD_EXAMPLES_NODESET_COMPILER**
-   Generate an OPC UA information model from a nodeset XML (experimental)
+   Compile unit tests. The tests can be executed with ``make test``
 
 **UA_BUILD_SELFSIGNED_CERTIFICATE**
    Generate a self-signed certificate for the server (openSSL required)
 
-UA_ENABLE_* group
-^^^^^^^^^^^^^^^^^
-
-This group contains build options related to the supported OPC UA features.
+Detailed SDK Features
+^^^^^^^^^^^^^^^^^^^^^
 
 **UA_ENABLE_SUBSCRIPTIONS**
    Enable subscriptions
+
 **UA_ENABLE_SUBSCRIPTIONS_EVENTS**
     Enable the use of events for subscriptions. This is a new feature and currently marked as EXPERIMENTAL.
+
 **UA_ENABLE_METHODCALLS**
    Enable the Method service set
+
 **UA_ENABLE_NODEMANAGEMENT**
    Enable dynamic addition and removal of nodes at runtime
+
 **UA_ENABLE_AMALGAMATION**
    Compile a single-file release into the files :file:`open62541.c` and :file:`open62541.h`
+
 **UA_ENABLE_MULTITHREADING**
    Enable multi-threading support
+
 **UA_ENABLE_IMMUTABLE_NODES**
-   Nodes in the information model are not edited but copied and replaced. The replacement is done with atomic operations so that the information model is always consistent and can be accessed from an interrupt or parallel thread (depends on the node storage plugin implementation). This feature is a prerequisite for ``UA_ENABLE_MULTITHREADING``.
+   Nodes in the information model are not edited but copied and replaced. The
+   replacement is done with atomic operations so that the information model is
+   always consistent and can be accessed from an interrupt or parallel thread
+   (depends on the node storage plugin implementation). This feature is a
+   prerequisite for ``UA_ENABLE_MULTITHREADING``.
+
 **UA_ENABLE_COVERAGE**
    Measure the coverage of unit tests
 
+**UA_NAMESPACE_ZERO**
+
+   Namespace zero contains the standard-defined nodes. The full namespace zero
+   may not be required for all applications. The selectable options are as follows:
+
+   - ``MINIMAL``: A barebones namespace zero that is compatible with most
+     clients. But this namespace 0 is so small that it does not pass the CTT
+     (Conformance Testing Tools of the OPC Foundation).
+   - ``REDUCED``: Small namespace zero that passes the CTT.
+   - ``FULL``: Full namespace zero generated from the official XML definitions.
+
+   The advanced build option ``UA_FILE_NS0`` can be used to override the XML
+   file used for namespace zero generation.
+
 Some options are marked as advanced. The advanced options need to be toggled to
 be visible in the cmake GUIs.
 
 **UA_ENABLE_TYPENAMES**
    Add the type and member names to the UA_DataType structure. Enabled by default.
+
 **UA_ENABLE_STATUSCODE_DESCRIPTIONS**
    Compile the human-readable name of the StatusCodes into the binary. Enabled by default.
-**UA_ENABLE_GENERATE_NAMESPACE0**
-   Generate and load UA XML Namespace 0 definition
-   ``UA_GENERATE_NAMESPACE0_FILE`` is used to specify the file for NS0 generation from namespace0 folder. Default value is ``Opc.Ua.NodeSet2.xml``
+
 **UA_ENABLE_NONSTANDARD_UDP**
    Enable udp extension
 
-UA_DEBUG_* group
-^^^^^^^^^^^^^^^^
+Debug Build Options
+^^^^^^^^^^^^^^^^^^^
 
 This group contains build options mainly useful for development of the library itself.
 
@@ -231,15 +250,33 @@ Minimizing the binary size
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 The size of the generated binary can be reduced considerably by adjusting the
-build configuration. First, in CMake, the build type can be set to
-``CMAKE_BUILD_TYPE=MinSizeRel``. This sets the compiler flags to minimize the
-binary size. The build type also strips out debug information. Second, the
-binary size can be reduced by removing features via the build-flags described
-above.
+build configuration. With open2541, it is possible to configure minimal servers
+that require less than 100kB of RAM and ROM.
 
-Especially, logging takes up a lot of space in the binary and might not be
+The following options influence the ROM requirements:
+
+First, in CMake, the build type can be set to ``CMAKE_BUILD_TYPE=MinSizeRel``.
+This sets the compiler flags to minimize the binary size. The build type also
+strips out debug information. Second, the binary size can be reduced by removing
+features via the build-flags described above.
+
+Second, setting ``UA_NAMESPACE_ZERO`` to ``MINIMAL`` reduces the size of the
+builtin information model. Setting this option can reduce the binary size by
+half in some cases.
+
+Third, some features might not be needed and can be disabled to reduce the
+binary footprint. Examples for this are Subscriptions or encrypted
+communication.
+
+Last, logging messages take up a lot of space in the binary and might not be
 needed in embedded scenarios. Setting ``UA_LOGLEVEL`` to a value above 600
-(=FATAL) disables all logging. In addition, the feature-flags
+(``FATAL``) disables all logging. In addition, the feature-flags
 ``UA_ENABLE_TYPENAMES`` and ``UA_ENABLE_STATUSCODE_DESCRIPTIONS`` add static
 information to the binary that is only used for human-readable logging and
 debugging.
+
+The RAM requirements of a server are mostly due to the following settings:
+
+- The size of the information model
+- The number of connected clients
+- The configured maximum message size that is preallocated

+ 1 - 0
include/ua_config.h.in

@@ -54,6 +54,7 @@ extern "C" {
 #cmakedefine UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
 #cmakedefine UA_ENABLE_VALGRIND_INTERACTIVE
 #define UA_VALGRIND_INTERACTIVE_INTERVAL ${UA_VALGRIND_INTERACTIVE_INTERVAL}
+#cmakedefine UA_GENERATED_NAMESPACE_ZERO
 
 /* Options for Debugging */
 #cmakedefine UA_DEBUG

+ 151 - 74
src/server/ua_server_ns0.c

@@ -69,20 +69,15 @@ addReferenceTypeNode(UA_Server *server, char* name, char *inverseName, UA_UInt32
                                    UA_QUALIFIEDNAME(0, name), reference_attr, NULL, NULL);
 }
 
-/**********************/
-/* Create Namespace 0 */
-/**********************/
+/***************************/
+/* Bootstrap NS0 hierarchy */
+/***************************/
 
 /* Creates the basic nodes which are expected by the nodeset compiler to be
  * already created. This is necessary to reduce the dependencies for the nodeset
  * compiler. */
 static UA_StatusCode
 UA_Server_createNS0_base(UA_Server *server) {
-
-    /*********************************/
-    /* Bootstrap reference hierarchy */
-    /*********************************/
-
     /* Bootstrap References and HasSubtype */
     UA_StatusCode ret = UA_STATUSCODE_GOOD;
     UA_ReferenceTypeAttributes references_attr = UA_ReferenceTypeAttributes_default;
@@ -275,6 +270,7 @@ readStatus(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
     return UA_STATUSCODE_GOOD;
 }
 
+#ifdef UA_GENERATED_NAMESPACE_ZERO
 static UA_StatusCode
 readServiceLevel(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
                  const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp,
@@ -324,6 +320,7 @@ readAuditing(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext
     }
     return UA_STATUSCODE_GOOD;
 }
+#endif
 
 static UA_StatusCode
 readNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
@@ -406,7 +403,7 @@ readCurrentTime(UA_Server *server, const UA_NodeId *sessionId, void *sessionCont
     return UA_STATUSCODE_GOOD;
 }
 
-#if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
+#if defined(UA_GENERATED_NAMESPACE_ZERO) && defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
 static UA_StatusCode
 readMonitoredItems(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
                    const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId,
@@ -462,6 +459,85 @@ writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
     return UA_Server_writeValue(server, UA_NODEID_NUMERIC(0, id), var);
 }
 
+#ifndef UA_GENERATED_NAMESPACE_ZERO
+static UA_StatusCode
+addVariableNode(UA_Server *server, char* name, UA_UInt32 variableid,
+                UA_UInt32 parentid, UA_UInt32 referenceid,
+                UA_Int32 valueRank, UA_UInt32 dataType) {
+    UA_VariableAttributes attr = UA_VariableAttributes_default;
+    attr.displayName = UA_LOCALIZEDTEXT("", name);
+    attr.dataType = UA_NODEID_NUMERIC(0, dataType);
+    attr.valueRank = valueRank;
+    attr.accessLevel = UA_ACCESSLEVELMASK_READ;
+    return UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(0, variableid),
+                                     UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NUMERIC(0, referenceid),
+                                     UA_QUALIFIEDNAME(0, name),
+                                     UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
+                                     attr, NULL, NULL);
+}
+
+/* A minimal server object that is not complete and does not use the mandated
+ * references to a server type. To be used on very constrained devices. */
+static UA_StatusCode
+UA_Server_minimalServerObject(UA_Server *server) {
+    /* Server */
+    UA_StatusCode retval = addObjectNode(server, "Server", UA_NS0ID_SERVER, UA_NS0ID_OBJECTSFOLDER,
+                                         UA_NS0ID_ORGANIZES, UA_NS0ID_BASEOBJECTTYPE);
+
+    retval |= addVariableNode(server, "ServerArray", UA_NS0ID_SERVER_SERVERARRAY,
+                              UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY, 1, UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "NamespaceArray", UA_NS0ID_SERVER_NAMESPACEARRAY,
+                              UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY, 1, UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "ServerStatus", UA_NS0ID_SERVER_SERVERSTATUS,
+                              UA_NS0ID_SERVER, UA_NS0ID_HASCOMPONENT, -1, UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "CurrentTime", UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME,
+                              UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, -1,
+                              UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "State", UA_NS0ID_SERVER_SERVERSTATUS_STATE,
+                              UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, -1,
+                              UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "BuildInfo", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO,
+                              UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, -1,
+                              UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "ProductUri", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI,
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, -1,
+                              UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "ManufacturerName",
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME,
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, -1,
+                              UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "ProductName",
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME,
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, -1,
+                              UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "SoftwareVersion",
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION,
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, -1,
+                              UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "BuildNumber",
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER,
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, -1,
+                              UA_NS0ID_BASEDATATYPE);
+
+    retval |= addVariableNode(server, "BuildDate",
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE,
+                              UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, -1,
+                              UA_NS0ID_BASEDATATYPE);
+
+    return retval;
+}
+#endif
+
 /* Initialize the nodeset 0 by using the generated code of the nodeset compiler.
  * This also initialized the data sources for various variables, such as for
  * example server time. */
@@ -476,15 +552,18 @@ UA_Server_initNS0(UA_Server *server) {
     if(retVal != UA_STATUSCODE_GOOD)
         return retVal;
 
+#ifdef UA_GENERATED_NAMESPACE_ZERO
     /* Load nodes and references generated from the XML ns0 definition */
-    server->bootstrapNS0 = true;
     retVal = ua_namespace0(server);
-    server->bootstrapNS0 = false;
+#else
+    /* Create a minimal server object */
+    UA_Server_minimalServerObject(server);
+#endif
 
     /* NamespaceArray */
-    UA_DataSource namespaceDataSource = {readNamespaces, NULL};
+    UA_DataSource namespaceDataSource = {readNamespaces, writeNamespaces};
     retVal |= UA_Server_setVariableNode_dataSource(server,
-                        UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY),
+                                                   UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY),
                                                    namespaceDataSource);
 
     /* ServerArray */
@@ -492,66 +571,10 @@ UA_Server_initNS0(UA_Server *server) {
                                     &server->config.applicationDescription.applicationUri,
                                     1, &UA_TYPES[UA_TYPES_STRING]);
 
-    /* LocaleIdArray */
-    UA_LocaleId locale_en = UA_STRING("en");
-    retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY,
-                                    &locale_en, 1, &UA_TYPES[UA_TYPES_LOCALEID]);
-
-    /* MaxBrowseContinuationPoints */
-    UA_UInt16 maxBrowseContinuationPoints = UA_MAXCONTINUATIONPOINTS;
-    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS,
-                               &maxBrowseContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
-
-    /* ServerProfileArray */
-    UA_String profileArray[5];
-    UA_UInt16 profileArraySize = 0;
-#define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING_ALLOC(x)
-    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NanoEmbeddedDevice");
-#ifdef UA_ENABLE_NODEMANAGEMENT
-    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement");
-#endif
-#ifdef UA_ENABLE_METHODCALLS
-    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods");
-#endif
-#ifdef UA_ENABLE_SUBSCRIPTIONS
-    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/EmbeddedDataChangeSubscription");
-#endif
-#ifdef UA_ENABLE_HISTORIZING
-    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/HistoricalRawData");
-#endif
-
-    retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY,
-                                    profileArray, profileArraySize, &UA_TYPES[UA_TYPES_STRING]);
-    for(int i=0; i<profileArraySize; i++) {
-        UA_String_deleteMembers(&profileArray[i]);
-    }
-
-    /* MaxQueryContinuationPoints */
-    UA_UInt16 maxQueryContinuationPoints = 0;
-    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXQUERYCONTINUATIONPOINTS,
-                               &maxQueryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
-
-    /* MaxHistoryContinuationPoints */
-    UA_UInt16 maxHistoryContinuationPoints = 0;
-    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXHISTORYCONTINUATIONPOINTS,
-                               &maxHistoryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
-
     /* MinSupportedSampleRate */
     retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MINSUPPORTEDSAMPLERATE,
                                &server->config.samplingIntervalLimits.min, &UA_TYPES[UA_TYPES_DURATION]);
 
-    /* ServerDiagnostics - ServerDiagnosticsSummary */
-    UA_ServerDiagnosticsSummaryDataType serverDiagnosticsSummary;
-    UA_ServerDiagnosticsSummaryDataType_init(&serverDiagnosticsSummary);
-    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY,
-                               &serverDiagnosticsSummary,
-                               &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE]);
-
-    /* ServerDiagnostics - EnabledFlag */
-    UA_Boolean enabledFlag = false;
-    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG,
-                               &enabledFlag, &UA_TYPES[UA_TYPES_BOOLEAN]);
-
     /* ServerStatus */
     UA_DataSource serverStatus = {readStatus, NULL};
     retVal |= UA_Server_setVariableNode_dataSource(server,
@@ -597,6 +620,8 @@ UA_Server_initNS0(UA_Server *server) {
     retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE,
                                &server->config.buildInfo.buildDate, &UA_TYPES[UA_TYPES_DATETIME]);
 
+#ifdef UA_GENERATED_NAMESPACE_ZERO
+
     /* SecondsTillShutdown */
     UA_UInt32 secondsTillShutdown = 0;
     retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN,
@@ -613,21 +638,72 @@ UA_Server_initNS0(UA_Server *server) {
     retVal |= UA_Server_setVariableNode_dataSource(server,
                         UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVICELEVEL), serviceLevel);
 
+    /* ServerDiagnostics - ServerDiagnosticsSummary */
+    UA_ServerDiagnosticsSummaryDataType serverDiagnosticsSummary;
+    UA_ServerDiagnosticsSummaryDataType_init(&serverDiagnosticsSummary);
+    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY,
+                               &serverDiagnosticsSummary,
+                               &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE]);
+
+    /* ServerDiagnostics - EnabledFlag */
+    UA_Boolean enabledFlag = false;
+    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG,
+                               &enabledFlag, &UA_TYPES[UA_TYPES_BOOLEAN]);
+
     /* Auditing */
     UA_DataSource auditing = {readAuditing, NULL};
     retVal |= UA_Server_setVariableNode_dataSource(server,
                         UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_AUDITING), auditing);
 
-    /* NamespaceArray */
-    UA_DataSource nsarray_datasource =  {readNamespaces, writeNamespaces};
-    retVal |= UA_Server_setVariableNode_dataSource(server,
-                        UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY), nsarray_datasource);
-
     /* Redundancy Support */
     UA_RedundancySupport redundancySupport = UA_REDUNDANCYSUPPORT_NONE;
     retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANCYSUPPORT,
                                &redundancySupport, &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
 
+    /* ServerCapabilities - LocaleIdArray */
+    UA_LocaleId locale_en = UA_STRING("en");
+    retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY,
+                                    &locale_en, 1, &UA_TYPES[UA_TYPES_LOCALEID]);
+
+    /* ServerCapabilities - MaxBrowseContinuationPoints */
+    UA_UInt16 maxBrowseContinuationPoints = UA_MAXCONTINUATIONPOINTS;
+    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS,
+                               &maxBrowseContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
+
+    /* ServerProfileArray */
+    UA_String profileArray[5];
+    UA_UInt16 profileArraySize = 0;
+#define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING(x)
+    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NanoEmbeddedDevice");
+#ifdef UA_ENABLE_NODEMANAGEMENT
+    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement");
+#endif
+#ifdef UA_ENABLE_METHODCALLS
+    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods");
+#endif
+#ifdef UA_ENABLE_SUBSCRIPTIONS
+    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/EmbeddedDataChangeSubscription");
+#endif
+#ifdef UA_ENABLE_HISTORIZING
+    ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/HistoricalRawData");
+#endif
+    retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY,
+                                    profileArray, profileArraySize, &UA_TYPES[UA_TYPES_STRING]);
+
+    /* ServerCapabilities - MaxQueryContinuationPoints */
+    UA_UInt16 maxQueryContinuationPoints = 0;
+    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXQUERYCONTINUATIONPOINTS,
+                               &maxQueryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
+
+    /* ServerCapabilities - MaxHistoryContinuationPoints */
+    UA_UInt16 maxHistoryContinuationPoints = 0;
+    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXHISTORYCONTINUATIONPOINTS,
+                               &maxHistoryContinuationPoints, &UA_TYPES[UA_TYPES_UINT16]);
+
+    /* ServerCapabilities - MinSupportedSampleRate */
+    retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MINSUPPORTEDSAMPLERATE,
+                               &server->config.samplingIntervalLimits.min, &UA_TYPES[UA_TYPES_DURATION]);
+
     /* ServerCapabilities - OperationLimits - MaxNodesPerRead */
     retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD,
                                &server->config.maxNodesPerRead, &UA_TYPES[UA_TYPES_UINT32]);
@@ -723,6 +799,7 @@ UA_Server_initNS0(UA_Server *server) {
                         UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_GETMONITOREDITEMS), readMonitoredItems);
 #endif
 
+#endif /* UA_GENERATED_NAMESPACE_ZERO */
 
     /* create the OverFlowEventType
      * The EventQueueOverflowEventType is defined as abstract, therefore we can not create an instance of that type

+ 1 - 1
tools/appveyor/build.ps1

@@ -70,7 +70,7 @@ try {
     Write-Host -ForegroundColor Green "`n##### Testing $env:CC_NAME with full NS0 #####`n"
     New-Item -ItemType directory -Path "build"
     cd build
-    & cmake -DUA_ENABLE_SUBSCRIPTIONS_EVENTS:BOOL=ON -DUA_BUILD_EXAMPLES:BOOL=ON -DUA_ENABLE_FULL_NS0:BOOL=ON -DUA_COMPILE_AS_CXX:BOOL=$env:FORCE_CXX -G"$env:CC_NAME"  ..
+    & cmake -DUA_ENABLE_SUBSCRIPTIONS_EVENTS:BOOL=ON -DUA_BUILD_EXAMPLES:BOOL=ON -DUA_NAMESPACE_ZERO:STRING=FULL -DUA_COMPILE_AS_CXX:BOOL=$env:FORCE_CXX -G"$env:CC_NAME"  ..
     Invoke-Expression $make_cmd
     if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) {
         Write-Host -ForegroundColor Red "`n`n*** Make failed. Exiting ... ***"

+ 2 - 2
tools/travis/travis_linux_script.sh

@@ -110,7 +110,7 @@ else
     echo -e "\r\n== Full Namespace 0 Generation ==" && echo -en 'travis_fold:start:script.build.ns0\\r'
     mkdir -p build
     cd build
-    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DCMAKE_BUILD_TYPE=Debug -DUA_ENABLE_FULL_NS0=ON -DUA_BUILD_EXAMPLES=ON  \
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DCMAKE_BUILD_TYPE=Debug -DUA_NAMESPACE_ZERO=FULL -DUA_BUILD_EXAMPLES=ON  \
     -DUA_ENABLE_SUBSCRIPTIONS_EVENTS=ON ..
     make -j
     if [ $? -ne 0 ] ; then exit 1 ; fi
@@ -238,7 +238,7 @@ else
     echo -e "\r\n== Unit tests (full NS0) ==" && echo -en 'travis_fold:start:script.build.unit_test_ns0_full\\r'
     mkdir -p build && cd build
     # Valgrind cannot handle the full NS0 because the generated file is too big. Thus run NS0 full without valgrind
-    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DUA_ENABLE_FULL_NS0=ON \
+    cmake -DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/$PYTHON -DUA_NAMESPACE_ZERO=FULL \
     -DCMAKE_BUILD_TYPE=Debug -DUA_BUILD_EXAMPLES=ON -DUA_ENABLE_PUBSUB=ON -DUA_ENABLE_ENCRYPTION=ON -DUA_ENABLE_DISCOVERY=ON \
     -DUA_ENABLE_DISCOVERY_MULTICAST=ON -DUA_BUILD_UNIT_TESTS=ON -DUA_ENABLE_COVERAGE=OFF \
     -DUA_ENABLE_UNIT_TESTS_MEMCHECK=OFF -DUA_ENABLE_SUBSCRIPTIONS_EVENTS=ON ..