blob: 5f4e404dd84046e9e48a25c18fc9c36102795132 [file] [log] [blame]
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
* Copyright 2017 (c) Julian Grothoff
* Copyright 2017 (c) Stefan Profanter, fortiss GmbH
*/
#ifndef UA_SERVER_NODES_H_
#define UA_SERVER_NODES_H_
/* !!! Warning !!!
*
* If you are not developing a nodestore plugin, then you should not work with
* the definitions from this file directly. The underlying node structures are
* not meant to be used directly by end users. Please use the public server API
* / OPC UA services to interact with the information model. */
#include <open62541/server.h>
_UA_BEGIN_DECLS
/* Forward declaration */
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
struct UA_MonitoredItem;
#endif
/**
* .. _information-modelling:
*
* 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
*
* Every node is identified by a unique (within the server) :ref:`nodeid`.
* Reference are triples of the form ``(source-nodeid, referencetype-nodeid,
* target-nodeid)``. An example reference between nodes is a
* ``hasTypeDefinition`` reference between a Variable and its VariableType. Some
* ReferenceTypes are *hierarchic* and must not form *directed loops*. See the
* section on :ref:`ReferenceTypes <referencetypenode>` for more details on
* possible references and their semantics.
*
* **Warning!!** The structures defined in this section are only relevant for
* the developers of custom Nodestores. The interaction with the information
* model is possible only via the OPC UA :ref:`services`. So the following
* sections are purely informational so that users may have a clear mental
* model of the underlying representation.
*
* Base Node Attributes
* --------------------
*
* Nodes contain attributes according to their node type. The base node
* attributes are common to all node types. In the OPC UA :ref:`services`,
* attributes are referred to via the :ref:`nodeid` of the containing node and
* an integer :ref:`attribute-id`.
*
* Internally, open62541 uses ``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. */
/* List of reference targets with the same reference type and direction */
typedef struct {
UA_NodeId referenceTypeId;
UA_Boolean isInverse;
size_t targetIdsSize;
UA_ExpandedNodeId *targetIds;
} UA_NodeReferenceKind;
#define UA_NODE_BASEATTRIBUTES \
UA_NodeId nodeId; \
UA_NodeClass nodeClass; \
UA_QualifiedName browseName; \
UA_LocalizedText displayName; \
UA_LocalizedText description; \
UA_UInt32 writeMask; \
size_t referencesSize; \
UA_NodeReferenceKind *references; \
\
/* Members specific to open62541 */ \
void *context; \
UA_Boolean constructed; /* Constructors were called */
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 (scalar) data type of the variable 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_NODE_VARIABLEATTRIBUTES \
/* Constraints on possible values */ \
UA_NodeId dataType; \
UA_Int32 valueRank; \
size_t arrayDimensionsSize; \
UA_UInt32 *arrayDimensions; \
\
/* The current value */ \
UA_ValueSource valueSource; \
union { \
struct { \
UA_DataValue value; \
UA_ValueCallback callback; \
} data; \
UA_DataSource dataSource; \
} value;
typedef struct {
UA_NODE_BASEATTRIBUTES
UA_NODE_VARIABLEATTRIBUTES
UA_Byte accessLevel;
UA_Double minimumSamplingInterval;
UA_Boolean historizing;
} UA_VariableNode;
/**
* .. _variabletypenode:
*
* VariableTypeNode
* ----------------
*
* VariableTypes are used to provide type definitions for variables.
* VariableTypes constrain the data type, value rank and array dimensions
* attributes of variable instances. Furthermore, instantiating from a specific
* variable type may provide semantic information. For example, an instance from
* ``MotorTemperatureVariableType`` is more meaningful than a float variable
* instantiated from ``BaseDataVariable``. */
typedef struct {
UA_NODE_BASEATTRIBUTES
UA_NODE_VARIABLEATTRIBUTES
UA_Boolean isAbstract;
/* Members specific to open62541 */
UA_NodeTypeLifecycle lifecycle;
} UA_VariableTypeNode;
/**
* .. _methodnode:
*
* MethodNode
* ----------
*
* Methods define callable functions and are invoked using the :ref:`Call
* <method-services>` service. MethodNodes may have special properties (variable
* childen with a ``hasProperty`` reference) with the :ref:`qualifiedname` ``(0,
* "InputArguments")`` and ``(0, "OutputArguments")``. The input and output
* arguments are both described via an array of ``UA_Argument``. While the Call
* service uses a generic array of :ref:`variant` for input and output, the
* actual argument values are checked to match the signature of the MethodNode.
*
* Note that the same MethodNode may be referenced from several objects (and
* object types). For this, the NodeId of the method *and of the object
* providing context* is part of a Call request message. */
typedef struct {
UA_NODE_BASEATTRIBUTES
UA_Boolean executable;
/* Members specific to open62541 */
UA_MethodCallback method;
} 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_NODE_BASEATTRIBUTES
#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
struct UA_MonitoredItem *monitoredItemQueue;
#endif
UA_Byte eventNotifier;
} UA_ObjectNode;
/**
* .. _objecttypenode:
*
* ObjectTypeNode
* --------------
*
* ObjectTypes provide definitions for Objects. Abstract objects cannot be
* instantiated. See :ref:`node-lifecycle` for the use of constructor and
* destructor callbacks. */
typedef struct {
UA_NODE_BASEATTRIBUTES
UA_Boolean isAbstract;
/* Members specific to open62541 */
UA_NodeTypeLifecycle lifecycle;
} UA_ObjectTypeNode;
/**
* .. _referencetypenode:
*
* ReferenceTypeNode
* -----------------
*
* Each reference between two nodes is typed with a ReferenceType that gives
* meaning to the relation. The OPC UA standard defines a set of ReferenceTypes
* as a mandatory part of OPC UA information models.
*
* - Abstract ReferenceTypes cannot be used in actual references and are only
* used to structure the ReferenceTypes hierarchy
* - Symmetric references have the same meaning from the perspective of the
* source and target node
*
* The figure below shows the hierarchy of the standard ReferenceTypes (arrows
* indicate a ``hasSubType`` relation). Refer to Part 3 of the OPC UA
* specification for the full semantics of each ReferenceType.
*
* .. graphviz::
*
* digraph tree {
*
* node [height=0, shape=box, fillcolor="#E5E5E5", concentrate=true]
*
* references [label="References\n(Abstract, Symmetric)"]
* hierarchical_references [label="HierarchicalReferences\n(Abstract)"]
* references -> hierarchical_references
*
* nonhierarchical_references [label="NonHierarchicalReferences\n(Abstract, Symmetric)"]
* references -> nonhierarchical_references
*
* haschild [label="HasChild\n(Abstract)"]
* hierarchical_references -> haschild
*
* aggregates [label="Aggregates\n(Abstract)"]
* haschild -> aggregates
*
* organizes [label="Organizes"]
* hierarchical_references -> organizes
*
* hascomponent [label="HasComponent"]
* aggregates -> hascomponent
*
* hasorderedcomponent [label="HasOrderedComponent"]
* hascomponent -> hasorderedcomponent
*
* hasproperty [label="HasProperty"]
* aggregates -> hasproperty
*
* hassubtype [label="HasSubtype"]
* haschild -> hassubtype
*
* hasmodellingrule [label="HasModellingRule"]
* nonhierarchical_references -> hasmodellingrule
*
* hastypedefinition [label="HasTypeDefinition"]
* nonhierarchical_references -> hastypedefinition
*
* hasencoding [label="HasEncoding"]
* nonhierarchical_references -> hasencoding
*
* hasdescription [label="HasDescription"]
* nonhierarchical_references -> hasdescription
*
* haseventsource [label="HasEventSource"]
* hierarchical_references -> haseventsource
*
* hasnotifier [label="HasNotifier"]
* hierarchical_references -> hasnotifier
*
* generatesevent [label="GeneratesEvent"]
* nonhierarchical_references -> generatesevent
*
* alwaysgeneratesevent [label="AlwaysGeneratesEvent"]
* generatesevent -> alwaysgeneratesevent
*
* {rank=same hierarchical_references nonhierarchical_references}
* {rank=same generatesevent haseventsource hasmodellingrule
* hasencoding hassubtype}
* {rank=same alwaysgeneratesevent hasproperty}
*
* }
*
* The ReferenceType hierarchy can be extended with user-defined ReferenceTypes.
* Many Companion Specifications for OPC UA define new ReferenceTypes to be used
* in their domain of interest.
*
* For the following example of custom ReferenceTypes, we attempt to model the
* structure of a technical system. For this, we introduce two custom
* ReferenceTypes. First, the hierarchical ``contains`` ReferenceType indicates
* that a system (represented by an OPC UA object) contains a component (or
* subsystem). This gives rise to a tree-structure of containment relations. For
* example, the motor (object) is contained in the car and the crankshaft is
* contained in the motor. Second, the symmetric ``connectedTo`` ReferenceType
* indicates that two components are connected. For example, the motor's
* crankshaft is connected to the gear box. Connections are independent of the
* containment hierarchy and can induce a general graph-structure. Further
* subtypes of ``connectedTo`` could be used to differentiate between physical,
* electrical and information related connections. A client can then learn the
* layout of a (physical) system represented in an OPC UA information model
* based on a common understanding of just two custom reference types. */
typedef struct {
UA_NODE_BASEATTRIBUTES
UA_Boolean isAbstract;
UA_Boolean symmetric;
UA_LocalizedText inverseName;
} UA_ReferenceTypeNode;
/**
* .. _datatypenode:
*
* DataTypeNode
* ------------
*
* DataTypes represent simple and structured data types. DataTypes may contain
* arrays. But they always describe the structure of a single instance. In
* open62541, DataTypeNodes in the information model hierarchy are matched to
* ``UA_DataType`` type descriptions for :ref:`generic-types` via their NodeId.
*
* Abstract DataTypes (e.g. ``Number``) cannot be the type of actual values.
* They are used to constrain values to possible child DataTypes (e.g.
* ``UInt32``). */
typedef struct {
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 information model to focus on a subset of nodes and
* references only. ViewNodes can be created and be interacted with. But their
* use in the :ref:`Browse<view-services>` service is currently unsupported in
* open62541. */
typedef struct {
UA_NODE_BASEATTRIBUTES
UA_Byte eventNotifier;
UA_Boolean containsNoLoops;
} UA_ViewNode;
/**
* Nodestore Plugin API
* ====================
*
* The following definitions are used for implementing custom node storage
* backends. **Most users will want to use the default nodestore and don't need
* to work with the nodestore API**.
*
* Outside of custom nodestore implementations, users should not manually edit
* nodes. Please use the OPC UA services for that. Otherwise, all consistency
* checks are omitted. This can crash the application eventually. */
/* For non-multithreaded access, some nodestores allow that nodes are edited
* without a copy/replace. This is not possible when the node is only an
* intermediate representation and stored e.g. in a database backend. */
extern const UA_Boolean inPlaceEditAllowed;
/* Nodestore context and lifecycle */
UA_StatusCode UA_Nodestore_new(void **nsCtx);
void UA_Nodestore_delete(void *nsCtx);
/**
* The following definitions are used to create empty nodes of the different
* node types. The memory is managed by the nodestore. Therefore, the node has
* to be removed via a special deleteNode function. (If the new node is not
* added to the nodestore.) */
UA_Node *
UA_Nodestore_newNode(void *nsCtx, UA_NodeClass nodeClass);
void
UA_Nodestore_deleteNode(void *nsCtx, UA_Node *node);
/**
*``Get`` returns a pointer to an immutable node. ``Release`` indicates that the
* pointer is no longer accessed afterwards. */
const UA_Node *
UA_Nodestore_getNode(void *nsCtx, const UA_NodeId *nodeId);
void
UA_Nodestore_releaseNode(void *nsCtx, const UA_Node *node);
/* Returns an editable copy of a node (needs to be deleted with the
* deleteNode function or inserted / replaced into the nodestore). */
UA_StatusCode
UA_Nodestore_getNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
UA_Node **outNode);
/* Inserts a new node into the nodestore. If the NodeId is zero, then a fresh
* numeric NodeId is assigned. If insertion fails, the node is deleted. */
UA_StatusCode
UA_Nodestore_insertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId);
/* To replace a node, get an editable copy of the node, edit and replace with
* this function. If the node was already replaced since the copy was made,
* UA_STATUSCODE_BADINTERNALERROR is returned. If the NodeId is not found,
* UA_STATUSCODE_BADNODEIDUNKNOWN is returned. In both error cases, the editable
* node is deleted. */
UA_StatusCode
UA_Nodestore_replaceNode(void *nsCtx, UA_Node *node);
/* Removes a node from the nodestore. */
UA_StatusCode
UA_Nodestore_removeNode(void *nsCtx, const UA_NodeId *nodeId);
/* Execute a callback for every node in the nodestore. */
typedef void (*UA_NodestoreVisitor)(void *visitorCtx, const UA_Node *node);
void
UA_Nodestore_iterate(void *nsCtx, UA_NodestoreVisitor visitor,
void *visitorCtx);
/**
* Node Handling
* =============
*
* To be used only in the nodestore and internally in the SDK. The following
* methods specialize internally for the different node classes, distinguished
* by the NodeClass attribute. */
/* Attributes must be of a matching type (VariableAttributes, ObjectAttributes,
* and so on). The attributes are copied. Note that the attributes structs do
* not contain NodeId, NodeClass and BrowseName. The NodeClass of the node needs
* to be correctly set before calling this method. UA_Node_deleteMembers is
* called on the node when an error occurs internally. */
UA_StatusCode UA_EXPORT
UA_Node_setAttributes(UA_Node *node, const void *attributes,
const UA_DataType *attributeType);
/* Reset the destination node and copy the content of the source */
UA_StatusCode UA_EXPORT
UA_Node_copy(const UA_Node *src, UA_Node *dst);
/* Allocate new node and copy the values from src */
UA_EXPORT UA_Node *
UA_Node_copy_alloc(const UA_Node *src);
/* Add a single reference to the node */
UA_StatusCode UA_EXPORT
UA_Node_addReference(UA_Node *node, const UA_AddReferencesItem *item);
/* Delete a single reference from the node */
UA_StatusCode UA_EXPORT
UA_Node_deleteReference(UA_Node *node, const UA_DeleteReferencesItem *item);
/* Delete all references of the node */
void UA_EXPORT
UA_Node_deleteReferences(UA_Node *node);
/* Remove all malloc'ed members of the node */
void UA_EXPORT
UA_Node_deleteMembers(UA_Node *node);
_UA_END_DECLS
#endif /* UA_SERVER_NODES_H_ */