Selaa lähdekoodia

add documentation of nodes; move generated datatype documentation

Julius Pfrommer 7 vuotta sitten
vanhempi
commit
d35b615c8f

+ 5 - 2
doc/CMakeLists.txt

@@ -26,12 +26,14 @@ generate_rst(${PROJECT_SOURCE_DIR}/include/ua_log.h ${DOC_SRC_DIR}/log.rst)
 generate_rst(${PROJECT_SOURCE_DIR}/include/ua_connection.h ${DOC_SRC_DIR}/connection.rst)
 generate_rst(${PROJECT_SOURCE_DIR}/src/server/ua_services.h ${DOC_SRC_DIR}/services.rst)
 generate_rst(${PROJECT_SOURCE_DIR}/src/server/ua_nodestore.h ${DOC_SRC_DIR}/nodestore.rst)
+generate_rst(${PROJECT_SOURCE_DIR}/src/server/ua_nodes.h ${DOC_SRC_DIR}/information_modelling.rst)
 
 add_custom_target(doc_latex ${SPHINX_EXECUTABLE}
   -b latex "${DOC_SRC_DIR}" "${DOC_LATEX_DIR}"
   DEPENDS ${DOC_SRC_DIR}/types.rst ${DOC_SRC_DIR}/constants.rst ${DOC_SRC_DIR}/types_generated.rst
           ${DOC_SRC_DIR}/server.rst ${DOC_SRC_DIR}/client.rst ${DOC_SRC_DIR}/client_highlevel.rst
-          ${DOC_SRC_DIR}/log.rst ${DOC_SRC_DIR}/connection.rst ${DOC_SRC_DIR}/services.rst ${DOC_SRC_DIR}/nodestore.rst
+          ${DOC_SRC_DIR}/log.rst ${DOC_SRC_DIR}/connection.rst ${DOC_SRC_DIR}/services.rst
+          ${DOC_SRC_DIR}/nodestore.rst ${DOC_SRC_DIR}/information_modelling.rst
   COMMENT "Building LaTeX sources for documentation with Sphinx")
 add_dependencies(doc_latex open62541)
 
@@ -48,6 +50,7 @@ add_custom_target(doc ${SPHINX_EXECUTABLE}
   -b html "${DOC_SRC_DIR}" "${DOC_HTML_DIR}"
   DEPENDS ${DOC_SRC_DIR}/types.rst ${DOC_SRC_DIR}/constants.rst ${DOC_SRC_DIR}/types_generated.rst
           ${DOC_SRC_DIR}/server.rst ${DOC_SRC_DIR}/client.rst ${DOC_SRC_DIR}/client_highlevel.rst
-          ${DOC_SRC_DIR}/log.rst ${DOC_SRC_DIR}/connection.rst ${DOC_SRC_DIR}/services.rst ${DOC_SRC_DIR}/nodestore.rst
+          ${DOC_SRC_DIR}/log.rst ${DOC_SRC_DIR}/connection.rst ${DOC_SRC_DIR}/services.rst
+          ${DOC_SRC_DIR}/nodestore.rst ${DOC_SRC_DIR}/information_modelling.rst
   COMMENT "Building HTML documentation with Sphinx")
 add_dependencies(doc open62541)

+ 3 - 1
doc/index.rst

@@ -24,7 +24,9 @@ standard.
    building
    tutorials
    types
-   constants
+   information_modelling
+   services
    server
    client
+   constants
    internal

+ 0 - 1
doc/internal.rst

@@ -3,7 +3,6 @@ Internals
 
 .. toctree::
 
-   services
    nodestore
    connection
    log

+ 22 - 14
include/ua_types.h

@@ -30,14 +30,14 @@ extern "C" {
  * ==========
  *
  * In open62541, all data types share the same basic API for creation, copying
- * and deletion. The header ua_types.h defines the builtin types. In addition,
- * we auto-generate ua_types_generated.h with additional types as well as the
- * following function definitions for all (builtin and generated) data types
- * ``T``.
+ * and deletion. The header ``ua_types.h`` defines the builtin data types. In
+ * addition, the auto-generated ``ua_types_generated.h`` contains additional
+ * data types making use of the builtin data types only. The following functions
+ * are defined for all (builtin and generated) data types ``T``:
  *
  * ``void T_init(T *ptr)``
  *   Initialize the data type. This is synonymous with zeroing out the memory,
- *   i.e. ``memset(dataptr, 0, sizeof(T))``.
+ *   i.e. ``memset(ptr, 0, sizeof(T))``.
  * ``T* T_new()``
  *   Allocate and return the memory for the data type. The memory is already
  *   initialized.
@@ -48,10 +48,7 @@ extern "C" {
  *   Delete the dynamically allocated content of the data type and perform a
  *   ``T_init`` to reset the type.
  * ``void T_delete(T *ptr)``
- *   Delete the content of the data type and the memory for the data type itself.
- *
- * OPC UA defines 25 builtin data types. All other data types are combinations
- * of the 25 builtin data types. */
+ *   Delete the content of the data type and the memory for the data type itself. */
 
 #define UA_BUILTIN_TYPES_COUNT 25U
 
@@ -554,15 +551,15 @@ typedef struct {
  * Variants can contain a single scalar or an array. For details on the handling
  * of arrays, see the Section `Array Handling`_. Array variants can have an
  * additional dimensionality (matrix, 3-tensor, ...) defined in an array of
- * dimension sizes. Higher rank dimensions are serialized first.
+ * dimension sizes.
  *
  * The differentiation between variants containing a scalar, an array or no data
  * is as follows:
  *
- * - arrayLength == 0 && data == NULL: no existing data
- * - arrayLength == 0 && data == UA_EMPTY_ARRAY_SENTINEL: array of length 0
- * - arrayLength == 0 && data > UA_EMPTY_ARRAY_SENTINEL: scalar value
- * - arrayLength > 0: array of the given length */
+ * - ``arrayLength == 0 && data == NULL``: the variant is empty
+ * - ``arrayLength == 0 && data == UA_EMPTY_ARRAY_SENTINEL``: array of length 0
+ * - ``arrayLength == 0 && data > UA_EMPTY_ARRAY_SENTINEL``: scalar value
+ * - ``arrayLength > 0``: array of the given length */
 typedef struct {
     const UA_DataType *type; /* The data type description */
     enum {
@@ -668,6 +665,8 @@ UA_Variant_setRangeCopy(UA_Variant *v, const void *array,
                         size_t arraySize, const UA_NumericRange range);
 
 /**
+ * .. _datavalue:
+ *
  * DataValue
  * ^^^^^^^^^
  * A data value with an associated status code and timestamps. */
@@ -807,6 +806,15 @@ void UA_EXPORT UA_random_seed(UA_UInt64 seed);
 UA_UInt32 UA_EXPORT UA_UInt32_random(void); /* no cryptographic entropy */
 UA_Guid UA_EXPORT UA_Guid_random(void);     /* no cryptographic entropy */
 
+/**
+ * Generated Data Type Definitions
+ * -------------------------------
+ *
+ * The following data types were auto-generated from a definition in XML format.
+ * Their exact definitions can be looked up here:
+ * https://opcfoundation.org/UA/schemas/Opc.Ua.Types.bsd.xml.
+ *
+ * .. include:: types_generated.rst */
 #ifdef __cplusplus
 } // extern "C"
 #endif

+ 1 - 0
src/server/ua_nodes.c

@@ -1,3 +1,4 @@
+#include "ua_server_internal.h"
 #include "ua_nodes.h"
 #include "ua_nodestore.h"
 #include "ua_util.h"

+ 189 - 75
src/server/ua_nodes.h

@@ -1,9 +1,41 @@
 #ifndef UA_NODES_H_
 #define UA_NODES_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include "ua_server.h"
 
-#define UA_STANDARD_NODEMEMBERS                 \
+/**
+ * Information Modelling
+ * =====================
+ *
+ * Information modelling in OPC UA combines concepts from object-orientation and
+ * semantic modelling. At the core, an OPC UA information model is a graph made
+ * up of
+ *
+ * - Nodes: There are eight possible node types (variable, object, method, ...)
+ * - References: Typed and directed relations between two nodes
+ *
+ * An example reference is a ``hasTypeDefinition`` reference between a variable
+ * and its variable type. See the section on :ref:`reference types
+ * <referencetypenode>` for more details about possible references and their
+ * semantics.
+ *
+ * The structures defined in this section are *not user-facing*. The interaction
+ * with the information model is possible only via the OPC UA :ref:`services`.
+ * Still, we reproduce how nodes are represented internally so that users may
+ * have a clear mental model.
+ *
+ * Base Node Attributes
+ * --------------------
+ *
+ * The following attributes are common to all nodes. We use ``UA_Node`` in
+ * places where the exact node type is not known or not important. The
+ * ``nodeClass`` attribute is used to ensure the correctness of casting from
+ * ``UA_Node`` to a specific node type. */
+#define UA_NODE_BASEATTRIBUTES                  \
     UA_NodeId nodeId;                           \
     UA_NodeClass nodeClass;                     \
     UA_QualifiedName browseName;                \
@@ -14,19 +46,86 @@
     size_t referencesSize;                      \
     UA_ReferenceNode *references;
 
+typedef struct {
+    UA_NODE_BASEATTRIBUTES
+} UA_Node;
+
+/**
+ * VariableNode
+ * ------------
+ *
+ * Variables store values in a :ref:`datavalue` together with
+ * metadata for introspection. Most notably, the attributes data type, value
+ * rank and array dimensions constrain the possible values the variable can take
+ * on.
+ *
+ * Variables come in two flavours: properties and datavariables. Properties are
+ * related to a parent with a ``hasProperty`` reference and may not have child
+ * nodes themselves. Datavariables may contain properties (``hasProperty``) and
+ * also datavariables (``hasComponents``).
+ *
+ * All variables are instances of some :ref:`variabletypenode` in return
+ * constraining the possible data type, value rank and array dimensions
+ * attributes.
+ *
+ * Data Type
+ * ^^^^^^^^^
+ *
+ * The type of the literal value is constrained to be of a specific type or one
+ * of its children in the type hierarchy. The data type is given as a nodeid
+ * pointing to a :ref:`datatypenode` in the type hierarchy. See the Section
+ * :ref:`datatypenode` for more details.
+ *
+ * If the data type attribute points to ``UInt32``, then the value attribute
+ * must be of that exact type since ``UInt32`` does not have children in the
+ * type hierarchy. If the data type attribute points ``Number``, then the type
+ * of the value attribute may still be ``UInt32``, but also ``Float`` or
+ * ``Byte``.
+ *
+ * Consistency between the data type attribute in the variable and its
+ * :ref:`VariableTypeNode` is ensured.
+ *
+ * Value Rank
+ * ^^^^^^^^^^
+ *
+ * This attribute indicates whether the value attribute of the variable is an
+ * array and how many dimensions the array has. It may have the following
+ * values:
+ *
+ * - ``n >= 1``: the value is an array with the specified number of dimensions
+ * - ``n =  0``: the value is an array with one or more dimensions
+ * - ``n = -1``: the value is a scalar
+ * - ``n = -2``: the value can be a scalar or an array with any number of dimensions
+ * - ``n = -3``: the value can be a scalar or a one dimensional array
+ *
+ * Consistency between the value rank attribute in the variable and its
+ * :ref:`variabletypenode` is ensured.
+ *
+ * Array Dimensions
+ * ^^^^^^^^^^^^^^^^
+ *
+ * If the value rank permits the value to be a (multi-dimensional) array, the
+ * exact length in each dimensions can be further constrained with this
+ * attribute.
+ *
+ * - For positive lengths, the variable value is guaranteed to be of the same
+ *   length in this dimension.
+ * - The dimension length zero is a wildcard and the actual value may have any
+ *   length in this dimension.
+ *
+ * Consistency between the array dimensions attribute in the variable and its
+ * :ref:`variabletypenode` is ensured. */
+/* Indicates whether a variable contains data inline or whether it points to an
+   external data source */
 typedef enum {
     UA_VALUESOURCE_DATA,
     UA_VALUESOURCE_DATASOURCE
 } UA_ValueSource;
 
-#define UA_VARIABLE_NODEMEMBERS                                         \
+#define UA_NODE_VARIABLEATTRIBUTES                                      \
     /* Constraints on possible values */                                \
     UA_NodeId dataType;                                                 \
-    UA_Int32 valueRank; /* n >= 1: the value is an array with the specified number of dimensions */       \
-                        /* n =  0: the value is an array with one or more dimensions */                   \
-                        /* n = -1: the value is a scalar  */                                              \
-                        /* n = -2: the value can be a scalar or an array with any number of dimensions */ \
-                        /* n = -3: the value can be a scalar or a one dimensional array */                \
+    UA_Int32 valueRank;                                                 \
     size_t arrayDimensionsSize;                                         \
     UA_UInt32 *arrayDimensions;                                         \
                                                                         \
@@ -40,101 +139,116 @@ typedef enum {
         UA_DataSource dataSource;                                       \
     } value;
 
-/****************/
-/* Generic Node */
-/****************/
+typedef struct {
+    UA_NODE_BASEATTRIBUTES
+    UA_NODE_VARIABLEATTRIBUTES
+    UA_Byte accessLevel;
+    UA_Byte userAccessLevel;
+    UA_Double minimumSamplingInterval;
+    UA_Boolean historizing; /* currently unsupported */
+} UA_VariableNode;
 
+/**
+ * .. _variabletypenode:
+ *
+ * VariableTypeNode
+ * ----------------
+ *
+ * VariableTypes are used to provide type definitions for variables. */
 typedef struct {
-    UA_STANDARD_NODEMEMBERS
-} UA_Node;
+    UA_NODE_BASEATTRIBUTES
+    UA_NODE_VARIABLEATTRIBUTES
+    UA_Boolean isAbstract;
+} UA_VariableTypeNode;
 
-void UA_Node_deleteMembersAnyNodeClass(UA_Node *node);
-UA_StatusCode UA_Node_copyAnyNodeClass(const UA_Node *src, UA_Node *dst);
+/**
+ * MethodNode
+ * ----------
+ *
+ * Methods define callable functions and are invoked using the Call service. */
+typedef struct {
+    UA_NODE_BASEATTRIBUTES
+    UA_Boolean executable;
+    UA_Boolean userExecutable;
 
-/**************/
-/* ObjectNode */
-/**************/
+    /* Members specific to open62541 */
+    void *methodHandle;
+    UA_MethodCallback attachedMethod;
+} UA_MethodNode;
 
+/**
+ * ObjectNode
+ * ----------
+ *
+ * Objects are used to represent systems, system components, real-world objects
+ * and software objects. Objects are instances of an :ref:`object
+ * type<objecttypenode>` and may contain variables, methods and further
+ * objects. */
 typedef struct {
-    UA_STANDARD_NODEMEMBERS
+    UA_NODE_BASEATTRIBUTES
     UA_Byte eventNotifier;
+
+    /* Members specific to open62541 */
     void *instanceHandle;
 } UA_ObjectNode;
 
-/******************/
-/* ObjectTypeNode */
-/******************/
-
+/**
+ * .. _objecttypenode:
+ *
+ * ObjectTypeNode
+ * --------------
+ *
+ * ObjectTypes provide definitions for Objects. */
 typedef struct {
-    UA_STANDARD_NODEMEMBERS
+    UA_NODE_BASEATTRIBUTES
     UA_Boolean isAbstract;
+
+    /* Members specific to open62541 */
     UA_ObjectLifecycleManagement lifecycleManagement;
 } UA_ObjectTypeNode;
 
-/****************/
-/* VariableNode */
-/****************/
-
+/**
+ * .. _referencetypenode:
+ *
+ * ReferenceTypeNode
+ * -----------------
+ *
+ * The OPC UA standard defines a set of ReferenceTypes as a mandatory part of
+ * OPC UA information models. */
 typedef struct {
-    UA_STANDARD_NODEMEMBERS
-    UA_VARIABLE_NODEMEMBERS
-    UA_Byte accessLevel;
-    UA_Byte userAccessLevel;
-    UA_Double minimumSamplingInterval;
-    UA_Boolean historizing;
-} UA_VariableNode;
-
-/********************/
-/* VariableTypeNode */
-/********************/
-
-typedef struct {
-    UA_STANDARD_NODEMEMBERS
-    UA_VARIABLE_NODEMEMBERS
-    UA_Boolean isAbstract;
-} UA_VariableTypeNode;
-
-/*********************/
-/* ReferenceTypeNode */
-/*********************/
-
-typedef struct {
-    UA_STANDARD_NODEMEMBERS
+    UA_NODE_BASEATTRIBUTES
     UA_Boolean isAbstract;
     UA_Boolean symmetric;
     UA_LocalizedText inverseName;
 } UA_ReferenceTypeNode;
 
-/**************/
-/* MethodNode */
-/**************/
-
+/**
+ * .. _datatypenode:
+ *
+ * DataTypeNode
+ * ------------
+ *
+ * The DataType Model is used to define simple and structured data types. */
 typedef struct {
-    UA_STANDARD_NODEMEMBERS
-    UA_Boolean executable;
-    UA_Boolean userExecutable;
-    void *methodHandle;
-    UA_MethodCallback attachedMethod;
-} UA_MethodNode;
-
-/************/
-/* ViewNode */
-/************/
+    UA_NODE_BASEATTRIBUTES
+    UA_Boolean isAbstract;
+} UA_DataTypeNode;
 
+/**
+ * ViewNode
+ * --------
+ *
+ * Each View defines a subset of the Nodes in the AddressSpace. Views can be
+ * used when browsing an informatin model to focus on a subset of nodes and
+ * references only. */
 typedef struct {
-    UA_STANDARD_NODEMEMBERS
+    UA_NODE_BASEATTRIBUTES
     UA_Byte eventNotifier;
-    /* <-- the same as objectnode until here --> */
     UA_Boolean containsNoLoops;
 } UA_ViewNode;
 
-/****************/
-/* DataTypeNode */
-/****************/
-
-typedef struct {
-    UA_STANDARD_NODEMEMBERS
-    UA_Boolean isAbstract;
-} UA_DataTypeNode;
+#ifdef __cplusplus
+} // extern "C"
+#endif
 
 #endif /* UA_NODES_H_ */

+ 1 - 0
src/server/ua_nodestore.c

@@ -1,4 +1,5 @@
 #include "ua_nodestore.h"
+#include "ua_server_internal.h"
 #include "ua_util.h"
 
 #ifndef UA_ENABLE_MULTITHREADING /* conditional compilation */

+ 49 - 0
src/server/ua_server_internal.h

@@ -78,6 +78,13 @@ struct UA_Server {
     UA_ServerConfig config;
 };
 
+/*****************/
+/* Node Handling */
+/*****************/
+
+void UA_Node_deleteMembersAnyNodeClass(UA_Node *node);
+UA_StatusCode UA_Node_copyAnyNodeClass(const UA_Node *src, UA_Node *dst);
+
 typedef UA_StatusCode (*UA_EditNodeCallback)(UA_Server*, UA_Session*, UA_Node*, const void*);
 
 /* Calls callback on the node. In the multithreaded case, the node is copied before and replaced in
@@ -159,4 +166,46 @@ UA_Variant_matchVariableDefinition(UA_Server *server, const UA_NodeId *variableD
                                    const UA_UInt32 *variableArrayDimensions, const UA_Variant *value,
                                    const UA_NumericRange *range, UA_Variant *equivalent);
 
+/*******************/
+/* Single-Services */
+/*******************/
+
+/* Some services take an array of "independent" requests. The single-services
+   are stored here to keep ua_services.h clean for documentation purposes. */
+
+UA_StatusCode
+Service_AddReferences_single(UA_Server *server, UA_Session *session,
+                             const UA_AddReferencesItem *item);
+
+UA_StatusCode
+Service_DeleteNodes_single(UA_Server *server, UA_Session *session,
+                           const UA_NodeId *nodeId, UA_Boolean deleteReferences);
+
+UA_StatusCode
+Service_DeleteReferences_single(UA_Server *server, UA_Session *session,
+                                const UA_DeleteReferencesItem *item);
+
+void Service_Browse_single(UA_Server *server, UA_Session *session,
+                           struct ContinuationPointEntry *cp,
+                           const UA_BrowseDescription *descr,
+                           UA_UInt32 maxrefs, UA_BrowseResult *result);
+
+void
+Service_TranslateBrowsePathsToNodeIds_single(UA_Server *server, UA_Session *session,
+                                             const UA_BrowsePath *path,
+                                             UA_BrowsePathResult *result);
+
+void Service_Read_single(UA_Server *server, UA_Session *session,
+                         UA_TimestampsToReturn timestamps,
+                         const UA_ReadValueId *id, UA_DataValue *v);
+
+UA_StatusCode Service_Write_single(UA_Server *server, UA_Session *session,
+                                   const UA_WriteValue *wvalue);
+
+void Service_Call_single(UA_Server *server, UA_Session *session,
+                         const UA_CallMethodRequest *request,
+                         UA_CallMethodResult *result);
+
+
+
 #endif /* UA_SERVER_INTERNAL_H_ */

+ 11 - 47
src/server/ua_services.h

@@ -14,11 +14,17 @@ extern "C" {
  *
  * Services
  * ========
- * The services defined in the OPC UA standard. */
+ *
+ * This section contains the services defined in the OPC UA standard grouped
+ * into service sets. Their definition is internal and *not visible to users*.
+ * Still, we present them here for an overview of the capabilities of OPC UA.
+ * Please refer to the :ref:`client` and :ref:`server` API where the services
+ * are exposed to end users. */
 /* Most services take as input the server, the current session and pointers to
-   the request and response. The possible error codes are returned as part of
-   the response. */
-typedef void (*UA_Service)(UA_Server*, UA_Session*, const void*, void*);
+   the request and response structures. Possible error codes are returned as
+   part of the response. */
+typedef void (*UA_Service)(UA_Server*, UA_Session*,
+                           const void *request, void *response);
 
 /**
  * Discovery Service Set
@@ -50,7 +56,7 @@ void Service_OpenSecureChannel(UA_Server *server, UA_Connection *connection,
                                const UA_OpenSecureChannelRequest *request,
                                UA_OpenSecureChannelResponse *response);
 
-/** Used to terminate a SecureChannel. */
+/* Used to terminate a SecureChannel. */
 void Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel);
 
 /**
@@ -103,27 +109,16 @@ void Service_AddReferences(UA_Server *server, UA_Session *session,
                            const UA_AddReferencesRequest *request,
                            UA_AddReferencesResponse *response);
 
-UA_StatusCode Service_AddReferences_single(UA_Server *server,
-                                           UA_Session *session,
-                                           const UA_AddReferencesItem *item);
-
 /* Used to delete one or more Nodes from the AddressSpace. */
 void Service_DeleteNodes(UA_Server *server, UA_Session *session,
                          const UA_DeleteNodesRequest *request,
                          UA_DeleteNodesResponse *response);
 
-UA_StatusCode Service_DeleteNodes_single(UA_Server *server, UA_Session *session,
-                                         const UA_NodeId *nodeId,
-                                         UA_Boolean deleteReferences);
-
 /* Used to delete one or more References of a Node. */
 void Service_DeleteReferences(UA_Server *server, UA_Session *session,
                               const UA_DeleteReferencesRequest *request,
                               UA_DeleteReferencesResponse *response);
 
-UA_StatusCode Service_DeleteReferences_single(UA_Server *server,
-                      UA_Session *session, const UA_DeleteReferencesItem *item);
-
 /**
  * View Service Set
  * ----------------
@@ -137,11 +132,6 @@ void Service_Browse(UA_Server *server, UA_Session *session,
                     const UA_BrowseRequest *request,
                     UA_BrowseResponse *response);
 
-void Service_Browse_single(UA_Server *server, UA_Session *session,
-                           struct ContinuationPointEntry *cp,
-                           const UA_BrowseDescription *descr,
-                           UA_UInt32 maxrefs, UA_BrowseResult *result);
-
 /* Used to request the next set of Browse or BrowseNext response information
  * that is too large to be sent in a single response. "Too large" in this
  * context means that the Server is not able to return a larger response or that
@@ -156,11 +146,6 @@ void Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *sessio
              const UA_TranslateBrowsePathsToNodeIdsRequest *request,
              UA_TranslateBrowsePathsToNodeIdsResponse *response);
 
-void Service_TranslateBrowsePathsToNodeIds_single(UA_Server *server,
-                                                  UA_Session *session,
-                                                  const UA_BrowsePath *path,
-                                                  UA_BrowsePathResult *result);
-
 /* Used by Clients to register the Nodes that they know they will access
  * repeatedly (e.g. Write, Call). It allows Servers to set up anything needed so
  * that the access operations will be more efficient. */
@@ -201,10 +186,6 @@ void Service_Read(UA_Server *server, UA_Session *session,
                   const UA_ReadRequest *request,
                   UA_ReadResponse *response);
 
-void Service_Read_single(UA_Server *server, UA_Session *session,
-                         UA_TimestampsToReturn timestamps,
-                         const UA_ReadValueId *id, UA_DataValue *v);
-
 /* Used to write one or more Attributes of one or more Nodes. For constructed
  * Attribute values whose elements are indexed, such as an array, this Service
  * allows Clients to write the entire set of indexed values as a composite, to
@@ -213,9 +194,6 @@ void Service_Write(UA_Server *server, UA_Session *session,
                    const UA_WriteRequest *request,
                    UA_WriteResponse *response);
 
-UA_StatusCode Service_Write_single(UA_Server *server, UA_Session *session,
-                                   const UA_WriteValue *wvalue);
-
 /* Not Implemented: Service_HistoryRead */
 /* Not Implemented: Service_HistoryUpdate */
 
@@ -224,7 +202,6 @@ UA_StatusCode Service_Write_single(UA_Server *server, UA_Session *session,
  * ------------------
  * The Method Service Set defines the means to invoke methods. A method shall be
  * a component of an Object. */
-#ifdef UA_ENABLE_METHODCALLS
 /* Used to call (invoke) a list of Methods. Each method call is invoked within
  * the context of an existing Session. If the Session is terminated, the results
  * of the method's execution cannot be returned to the Client and are
@@ -233,19 +210,12 @@ void Service_Call(UA_Server *server, UA_Session *session,
                   const UA_CallRequest *request,
                   UA_CallResponse *response);
 
-void Service_Call_single(UA_Server *server, UA_Session *session,
-                         const UA_CallMethodRequest *request,
-                         UA_CallMethodResult *result);
-#endif
-
 /**
  * MonitoredItem Service Set
  * -------------------------
  * Clients define MonitoredItems to subscribe to data and Events. Each
  * MonitoredItem identifies the item to be monitored and the Subscription to use
  * to send Notifications. The item to be monitored may be any Node Attribute. */
-#ifdef UA_ENABLE_SUBSCRIPTIONS
-
 /* Used to create and add one or more MonitoredItems to a Subscription. A
  * MonitoredItem is deleted automatically by the Server when the Subscription is
  * deleted. Deleting a MonitoredItem causes its entire set of triggered item
@@ -273,14 +243,10 @@ void Service_SetMonitoringMode(UA_Server *server, UA_Session *session,
 
 /* Not Implemented: Service_SetTriggering */
 
-#endif
-
 /**
  * Subscription Service Set
  * ------------------------
  * Subscriptions are used to report Notifications to the Client. */
-#ifdef UA_ENABLE_SUBSCRIPTIONS
-
 /* Used to create a Subscription. Subscriptions monitor a set of MonitoredItems
  * for Notifications and return them to the Client in response to Publish
  * requests. */
@@ -323,8 +289,6 @@ void Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
 
 /* Not Implemented: Service_TransferSubscription */
 
-#endif
-
 #ifdef __cplusplus
 } // extern "C"
 #endif

+ 1 - 3
src/server/ua_services_attribute.c

@@ -1020,12 +1020,10 @@ __UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
     UA_WriteValue_init(&wvalue);
     wvalue.nodeId = *nodeId;
     wvalue.attributeId = attributeId;
-    if(attributeId != UA_ATTRIBUTEID_VALUE) {
+    if(attr_type != &UA_TYPES[UA_TYPES_VARIANT]) {
         /* hacked cast. the target WriteValue is used as const anyway */
         UA_Variant_setScalar(&wvalue.value.value, (void*)(uintptr_t)value, attr_type);
     } else {
-        if(attr_type != &UA_TYPES[UA_TYPES_VARIANT])
-            return UA_STATUSCODE_BADTYPEMISMATCH;
         wvalue.value.value = *(const UA_Variant*)value;
     }
     wvalue.value.hasValue = true;

+ 1 - 1
tools/c2rst.py

@@ -13,7 +13,7 @@ import re
 # - Find the last line beginning with "#ifdef" -> end of the documentation
 
 remove_keyword = [" UA_EXPORT", " UA_FUNC_ATTR_WARN_UNUSED_RESULT",
-                  " UA_FUNC_ATTR_MALLOC"]
+                  " UA_FUNC_ATTR_MALLOC", " UA_RESTRICT "]
 
 def clean_comment(line):
     m = re.search("^( \* |/\*\* )(.*?)( \*/)?$", line)

+ 6 - 8
tools/generate_datatypes.py

@@ -414,21 +414,19 @@ extern "C" {
 #endif
 
 #include "ua_types.h"
-''' + ('\n#include "ua_types_generated.h"\n' if outname != "ua_types" else '') + '''
-
-/**
- * Additional Data Type Definitions
- * ================================
- */
-''')
+''' + ('\n#include "ua_types_generated.h"\n' if outname != "ua_types" else ''))
 
+printh('''/**
+ * Every type is assigned an index in an array containing the type descriptions.
+ * These descriptions are used during type handling (copying, deletion,
+ * binary encoding, ...). */''')
 printh("#define " + outname.upper() + "_COUNT %s" % (str(len(selected_types))))
 printh("extern UA_EXPORT const UA_DataType " + outname.upper() + "[" + outname.upper() + "_COUNT];")
 
 i = 0
 for t in iter_types(types):
     printh("\n/**\n * " +  t.name)
-    printh(" * " + "-" * len(t.name))
+    printh(" * " + "^" * len(t.name))
     if t.description == "":
         printh(" */")
     else: