Pārlūkot izejas kodu

add typed version of writeAttribute highlevel functions; add documention for the highlevel client

Julius Pfrommer 8 gadi atpakaļ
vecāks
revīzija
85f04d57c7

+ 3 - 0
doc/CMakeLists.txt

@@ -16,6 +16,7 @@ generate_rst(${PROJECT_SOURCE_DIR}/include/ua_constants.h ${PROJECT_BINARY_DIR}/
 generate_rst(${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.h ${PROJECT_BINARY_DIR}/doc_src/types_generated.rst)
 generate_rst(${PROJECT_SOURCE_DIR}/include/ua_server.h ${PROJECT_BINARY_DIR}/doc_src/server.rst)
 generate_rst(${PROJECT_SOURCE_DIR}/include/ua_client.h ${PROJECT_BINARY_DIR}/doc_src/client.rst)
+generate_rst(${PROJECT_SOURCE_DIR}/include/ua_client_highlevel.h ${PROJECT_BINARY_DIR}/doc_src/client_highlevel.rst)
 generate_rst(${PROJECT_SOURCE_DIR}/include/ua_log.h ${PROJECT_BINARY_DIR}/doc_src/log.rst)
 generate_rst(${PROJECT_SOURCE_DIR}/include/ua_connection.h ${PROJECT_BINARY_DIR}/doc_src/connection.rst)
 generate_rst(${PROJECT_SOURCE_DIR}/src/server/ua_services.h ${PROJECT_BINARY_DIR}/doc_src/services.rst)
@@ -28,6 +29,7 @@ add_custom_target(doc_latex ${SPHINX_EXECUTABLE}
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/types_generated.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/server.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/client.rst
+  DEPENDS ${PROJECT_BINARY_DIR}/doc_src/client_highlevel.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/log.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/connection.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/services.rst
@@ -43,6 +45,7 @@ add_custom_target(doc ${SPHINX_EXECUTABLE}
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/types_generated.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/server.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/client.rst
+  DEPENDS ${PROJECT_BINARY_DIR}/doc_src/client_highlevel.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/log.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/connection.rst
   DEPENDS ${PROJECT_BINARY_DIR}/doc_src/services.rst

+ 1 - 0
doc/index.rst

@@ -27,5 +27,6 @@ standard.
    constants
    server
    client
+   client_highlevel
    internal
 

+ 256 - 165
include/ua_client_highlevel.h

@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2014-2016 the contributors as stated in the AUTHORS file
+ *
+ * This file is part of open62541. open62541 is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU Lesser General
+ * Public License, version 3 (as published by the Free Software Foundation) with
+ * a static linking exception as stated in the LICENSE file provided with
+ * open62541.
+ *
+ * open62541 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ */
+
 #ifndef UA_CLIENT_HIGHLEVEL_H_
 #define UA_CLIENT_HIGHLEVEL_H_
 
@@ -8,32 +23,219 @@ extern "C" {
 #include "ua_client.h"
 
 /**
- * Get the namespace-index of a namespace-URI
- *
- * @param client The UA_Client struct for this connection
- * @param namespaceUri The interested namespace URI
- * @param namespaceIndex The namespace index of the URI. The value is unchanged in case of an error
- * @return Indicates whether the operation succeeded or returns an error code
- */
+ * Highlevel Client Functionality
+ * ------------------------------
+ * The following definitions are convenience functions making use of the
+ * standard OPC UA services in the background. */
+/**
+ * Read Attributes
+ * ===============
+ * The following functions can be used to retrieve a single node attribute. Use
+ * the regular service to read several attributes at once. */
+/* Don't call this function, use the typed versions */
 UA_StatusCode UA_EXPORT
-UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri, UA_UInt16 *namespaceIndex);
+__UA_Client_readAttribute(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId,
+                          void *out, const UA_DataType *outDataType);
 
-#ifndef HAVE_NODEITER_CALLBACK
-#define HAVE_NODEITER_CALLBACK
-/* Iterate over all nodes referenced by parentNodeId by calling the callback
-   function for each child node */                                                        
-typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse,
-                                                  UA_NodeId referenceTypeId, void *handle);
-#endif
- 
+static UA_INLINE UA_StatusCode
+UA_Client_readNodeIdAttribute(UA_Client *client, UA_NodeId nodeId, UA_NodeId *outNodeId) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_NODEID, outNodeId, &UA_TYPES[UA_TYPES_NODEID]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readNodeClassAttribute(UA_Client *client, UA_NodeId nodeId, UA_NodeClass *outNodeClass) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_NODECLASS, outNodeClass, &UA_TYPES[UA_TYPES_NODECLASS]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readBrowseNameAttribute(UA_Client *client, UA_NodeId nodeId, UA_QualifiedName *outBrowseName) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_BROWSENAME, outBrowseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readDisplayNameAttribute(UA_Client *client, UA_NodeId nodeId, UA_LocalizedText *outDisplayName) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_DISPLAYNAME, outDisplayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readDescriptionAttribute(UA_Client *client, UA_NodeId nodeId, UA_LocalizedText *outDescription) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_DESCRIPTION, outDescription, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readWriteMaskAttribute(UA_Client *client, UA_NodeId nodeId, UA_UInt32 *outWriteMask) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_WRITEMASK, outWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readUserWriteMaskAttribute(UA_Client *client, UA_NodeId nodeId, UA_UInt32 *outUserWriteMask) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_USERWRITEMASK, outUserWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readIsAbstractAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outIsAbstract) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_ISABSTRACT, outIsAbstract, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readSymmetricAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outSymmetric) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_SYMMETRIC, outSymmetric, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readInverseNameAttribute(UA_Client *client, UA_NodeId nodeId, UA_LocalizedText *outInverseName) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_INVERSENAME, outInverseName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readContainsNoLoopsAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outContainsNoLoops) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS, outContainsNoLoops, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readEventNotifierAttribute(UA_Client *client, UA_NodeId nodeId, UA_Byte *outEventNotifier) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER, outEventNotifier, &UA_TYPES[UA_TYPES_BYTE]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readValueAttribute(UA_Client *client, UA_NodeId nodeId, UA_Variant *outValue) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_VALUE, outValue, &UA_TYPES[UA_TYPES_VARIANT]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readDataTypeAttribute(UA_Client *client, UA_NodeId nodeId, UA_NodeId *outDataType) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_DATATYPE, outDataType, &UA_TYPES[UA_TYPES_NODEID]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readValueRankAttribute(UA_Client *client, UA_NodeId nodeId, UA_Int32 *outValueRank) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_VALUERANK, outValueRank, &UA_TYPES[UA_TYPES_INT32]); }
+
+// todo: fetch an array
+static UA_INLINE UA_StatusCode
+UA_Client_readArrayDimensionsAttribute(UA_Client *client, UA_NodeId nodeId, UA_Int32 *outArrayDimensions) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS, outArrayDimensions, &UA_TYPES[UA_TYPES_INT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readAccessLevelAttribute(UA_Client *client, UA_NodeId nodeId, UA_UInt32 *outAccessLevel) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_ACCESSLEVEL, outAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readUserAccessLevelAttribute(UA_Client *client, UA_NodeId nodeId, UA_UInt32 *outUserAccessLevel) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL, outUserAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readMinimumSamplingIntervalAttribute(UA_Client *client, UA_NodeId nodeId, UA_Double *outMinimumSamplingInterval) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL, outMinimumSamplingInterval, &UA_TYPES[UA_TYPES_DOUBLE]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readHistorizingAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outHistorizing) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_HISTORIZING, outHistorizing, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readExecutableAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outExecutable) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_EXECUTABLE, outExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_readUserExecutableAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outUserExecutable) {
+    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_USEREXECUTABLE, outUserExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+/**
+ * Write Attributes
+ * ================
+ * The following functions can be use to write a single node attribute at a
+ * time. Use the regular write service to write several attributes at once. */
+/* Don't call this function, use the typed versions */
 UA_StatusCode UA_EXPORT
-UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId,
-                               UA_NodeIteratorCallback callback, void *handle) ;
+__UA_Client_writeAttribute(UA_Client *client, UA_NodeId nodeId,
+                           UA_AttributeId attributeId, const void *in,
+                           const UA_DataType *inDataType);
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeNodeIdAttribute(UA_Client *client, UA_NodeId nodeId, const UA_NodeId *newNodeId) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_NODEID, newNodeId, &UA_TYPES[UA_TYPES_NODEID]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeNodeClassAttribute(UA_Client *client, UA_NodeId nodeId, const UA_NodeClass *newNodeClass) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_NODECLASS, newNodeClass, &UA_TYPES[UA_TYPES_NODECLASS]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeBrowseNameAttribute(UA_Client *client, UA_NodeId nodeId, const UA_QualifiedName *newBrowseName) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_BROWSENAME, newBrowseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
+    
+static UA_INLINE UA_StatusCode
+UA_Client_writeDisplayNameAttribute(UA_Client *client, UA_NodeId nodeId, const UA_LocalizedText *newDisplayName) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_DISPLAYNAME, newDisplayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeDescriptionAttribute(UA_Client *client, UA_NodeId nodeId, const UA_LocalizedText *newDescription) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_DESCRIPTION, newDescription, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeWriteMaskAttribute(UA_Client *client, UA_NodeId nodeId, const UA_UInt32 *newWriteMask) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_WRITEMASK, newWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeUserWriteMaskAttribute(UA_Client *client, UA_NodeId nodeId, const UA_UInt32 *newUserWriteMask) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_USERWRITEMASK, newUserWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeIsAbstractAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Boolean *newIsAbstract) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_ISABSTRACT, newIsAbstract, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeSymmetricAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Boolean *newSymmetric) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_SYMMETRIC, newSymmetric, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeInverseNameAttribute(UA_Client *client, UA_NodeId nodeId, const UA_LocalizedText *newInverseName) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_INVERSENAME, newInverseName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeContainsNoLoopsAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Boolean *newContainsNoLoops) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS, newContainsNoLoops, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeEventNotifierAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Byte *newEventNotifier) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER, newEventNotifier, &UA_TYPES[UA_TYPES_BYTE]); }
+    
+static UA_INLINE UA_StatusCode
+UA_Client_writeValueAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Variant *newValue) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_VALUE, newValue, &UA_TYPES[UA_TYPES_VARIANT]); }
+                                     
+static UA_INLINE UA_StatusCode
+UA_Client_writeDataTypeAttribute(UA_Client *client, UA_NodeId nodeId, const UA_NodeId *newDataType) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_DATATYPE, newDataType, &UA_TYPES[UA_TYPES_NODEID]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeValueRankAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Int32 *newValueRank) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_VALUERANK, newValueRank, &UA_TYPES[UA_TYPES_INT32]); }
 
-/*******************/
-/* Node Management */
-/*******************/
+// todo: write an array
+static UA_INLINE UA_StatusCode
+UA_Client_writeArrayDimensionsAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Int32 *newArrayDimensions) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS, newArrayDimensions, &UA_TYPES[UA_TYPES_INT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeAccessLevelAttribute(UA_Client *client, UA_NodeId nodeId, const UA_UInt32 *newAccessLevel) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_ACCESSLEVEL, newAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeUserAccessLevelAttribute(UA_Client *client, UA_NodeId nodeId, const UA_UInt32 *newUserAccessLevel) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL, newUserAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeMinimumSamplingIntervalAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Double *newMinimumSamplingInterval) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL, newMinimumSamplingInterval, &UA_TYPES[UA_TYPES_DOUBLE]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeHistorizingAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Boolean *newHistorizing) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_HISTORIZING, newHistorizing, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeExecutableAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Boolean *newExecutable) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_EXECUTABLE, newExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
+
+static UA_INLINE UA_StatusCode
+UA_Client_writeUserExecutableAttribute(UA_Client *client, UA_NodeId nodeId, const UA_Boolean *newUserExecutable) {
+    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_USEREXECUTABLE, newUserExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
 
+/**
+ * Method Calling
+ * ============== */
+UA_StatusCode UA_EXPORT
+UA_Client_call(UA_Client *client, const UA_NodeId objectId, const UA_NodeId methodId,
+               size_t inputSize, const UA_Variant *input, size_t *outputSize, UA_Variant **output);
+
+/**
+ * Node Management
+ * =============== */
 UA_StatusCode UA_EXPORT
 UA_Client_addReference(UA_Client *client, const UA_NodeId sourceNodeId, const UA_NodeId referenceTypeId,
                        UA_Boolean isForward, const UA_String targetServerUri,
@@ -135,147 +337,9 @@ UA_Client_addMethodNode(UA_Client *client, const UA_NodeId requestedNewNodeId,
                                (const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_METHODATTRIBUTES],
                                outNewNodeId); }
 
-/*************************/
-/* Attribute Service Set */
-/*************************/
-
-/* Don't use this function. There are typed versions for every supported attribute. */
-UA_StatusCode UA_EXPORT
-__UA_Client_readAttribute(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId,
-                          void *out, const UA_DataType *outDataType);
-
-UA_StatusCode UA_EXPORT
-__UA_Client_writeAttribute(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId,
-                           void *in, const UA_DataType *inDataType);
-
-static UA_INLINE UA_StatusCode
-UA_Client_readNodeIdAttribute(UA_Client *client, UA_NodeId nodeId, UA_NodeId *outNodeId) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_NODEID,
-                                     outNodeId, &UA_TYPES[UA_TYPES_NODEID]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readNodeClassAttribute(UA_Client *client, UA_NodeId nodeId, UA_NodeClass *outNodeClass) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_NODECLASS,
-                                     outNodeClass, &UA_TYPES[UA_TYPES_NODECLASS]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readBrowseNameAttribute(UA_Client *client, UA_NodeId nodeId, UA_QualifiedName *outBrowseName) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_BROWSENAME,
-                                     outBrowseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readDisplayNameAttribute(UA_Client *client, UA_NodeId nodeId, UA_LocalizedText *outDisplayName) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_DISPLAYNAME,
-                                     outDisplayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readDescriptionAttribute(UA_Client *client, UA_NodeId nodeId, UA_LocalizedText *outDescription) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_DESCRIPTION,
-                                     outDescription, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readWriteMaskAttribute(UA_Client *client, UA_NodeId nodeId, UA_UInt32 *outWriteMask) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_WRITEMASK,
-                                     outWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readUserWriteMaskAttribute(UA_Client *client, UA_NodeId nodeId, UA_UInt32 *outUserWriteMask) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_USERWRITEMASK,
-                                     outUserWriteMask, &UA_TYPES[UA_TYPES_UINT32]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readIsAbstractAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outIsAbstract) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_ISABSTRACT,
-                                     outIsAbstract, &UA_TYPES[UA_TYPES_BOOLEAN]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readSymmetricAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outSymmetric) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_SYMMETRIC,
-                                     outSymmetric, &UA_TYPES[UA_TYPES_BOOLEAN]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readInverseNameAttribute(UA_Client *client, UA_NodeId nodeId, UA_LocalizedText *outInverseName) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_INVERSENAME,
-                                     outInverseName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readContainsNoLoopsAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outContainsNoLoops) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_CONTAINSNOLOOPS,
-                                     outContainsNoLoops, &UA_TYPES[UA_TYPES_BOOLEAN]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readEventNotifierAttribute(UA_Client *client, UA_NodeId nodeId, UA_Byte *outEventNotifier) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_EVENTNOTIFIER,
-                                     outEventNotifier, &UA_TYPES[UA_TYPES_BYTE]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readValueAttribute(UA_Client *client, UA_NodeId nodeId, UA_Variant *outValue) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_VALUE,
-                                     outValue, &UA_TYPES[UA_TYPES_VARIANT]); }
-static UA_INLINE UA_StatusCode
-UA_Client_writeValueAttribute(UA_Client *client, UA_NodeId nodeId, UA_Variant *inValue) {
-    return __UA_Client_writeAttribute(client, nodeId, UA_ATTRIBUTEID_VALUE,
-                                     inValue, &UA_TYPES[UA_TYPES_VARIANT]); }
-                                     
-static UA_INLINE UA_StatusCode
-UA_Client_readDataTypeAttribute(UA_Client *client, UA_NodeId nodeId, UA_NodeId *outDataType) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_DATATYPE,
-                                     outDataType, &UA_TYPES[UA_TYPES_NODEID]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readValueRankAttribute(UA_Client *client, UA_NodeId nodeId, UA_Int32 *outValueRank) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_VALUERANK,
-                                     outValueRank, &UA_TYPES[UA_TYPES_INT32]); }
-
-// todo: fetch an array
-static UA_INLINE UA_StatusCode
-UA_Client_readArrayDimensionsAttribute(UA_Client *client, UA_NodeId nodeId, UA_Int32 *outArrayDimensions) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_ARRAYDIMENSIONS,
-                                     outArrayDimensions, &UA_TYPES[UA_TYPES_INT32]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readAccessLevelAttribute(UA_Client *client, UA_NodeId nodeId, UA_UInt32 *outAccessLevel) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_ACCESSLEVEL,
-                                     outAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readUserAccessLevelAttribute(UA_Client *client, UA_NodeId nodeId, UA_UInt32 *outUserAccessLevel) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_USERACCESSLEVEL,
-                                     outUserAccessLevel, &UA_TYPES[UA_TYPES_UINT32]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readMinimumSamplingIntervalAttribute(UA_Client *client, UA_NodeId nodeId,
-                                               UA_Double *outMinimumSamplingInterval) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
-                                     outMinimumSamplingInterval, &UA_TYPES[UA_TYPES_DOUBLE]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readHistorizingAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outHistorizing) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_HISTORIZING,
-                                     outHistorizing, &UA_TYPES[UA_TYPES_BOOLEAN]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readExecutableAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outExecutable) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_EXECUTABLE,
-                                     outExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
-
-static UA_INLINE UA_StatusCode
-UA_Client_readUserExecutableAttribute(UA_Client *client, UA_NodeId nodeId, UA_Boolean *outUserExecutable) {
-    return __UA_Client_readAttribute(client, nodeId, UA_ATTRIBUTEID_USEREXECUTABLE,
-                                     outUserExecutable, &UA_TYPES[UA_TYPES_BOOLEAN]); }
-
-/**********************/
-/* Method Service Set */
-/**********************/
-
-UA_StatusCode UA_EXPORT
-UA_Client_call(UA_Client *client, const UA_NodeId objectId, const UA_NodeId methodId,
-               size_t inputSize, const UA_Variant *input, size_t *outputSize, UA_Variant **output);
-
-/**************************/
-/* Subscriptions Handling */
-/**************************/
-
+/**
+ * Subscriptions Handling
+ * ====================== */
 #ifdef UA_ENABLE_SUBSCRIPTIONS
 
 typedef struct {
@@ -298,17 +362,44 @@ UA_Client_Subscriptions_remove(UA_Client *client, UA_UInt32 subscriptionId);
 
 UA_StatusCode UA_EXPORT UA_Client_Subscriptions_manuallySendPublishRequest(UA_Client *client);
 
+typedef void (*UA_MonitoredItemHandlingFunction) (UA_UInt32 handle, UA_DataValue *value, void *context);
+
 UA_StatusCode UA_EXPORT
 UA_Client_Subscriptions_addMonitoredItem(UA_Client *client, UA_UInt32 subscriptionId,
                                          UA_NodeId nodeId, UA_UInt32 attributeID,
-                                         void (*handlingFunction)(UA_UInt32 handle, UA_DataValue *value, void *context),
-                                         void *handlingContext,
-                                         UA_UInt32 *newMonitoredItemId);
+                                         UA_MonitoredItemHandlingFunction handlingFunction,
+                                         void *handlingContext, UA_UInt32 *newMonitoredItemId);
 
 UA_StatusCode UA_EXPORT
 UA_Client_Subscriptions_removeMonitoredItem(UA_Client *client, UA_UInt32 subscriptionId,
                                             UA_UInt32 monitoredItemId);
+
+#endif
+
+/**
+ * Misc Highlevel Functionality
+ * ============================ */
+/* Get the namespace-index of a namespace-URI
+ *
+ * @param client The UA_Client struct for this connection
+ * @param namespaceUri The interested namespace URI
+ * @param namespaceIndex The namespace index of the URI. The value is unchanged
+ *        in case of an error
+ * @return Indicates whether the operation succeeded or returns an error code */
+UA_StatusCode UA_EXPORT
+UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri, UA_UInt16 *namespaceIndex);
+
+#ifndef HAVE_NODEITER_CALLBACK
+#define HAVE_NODEITER_CALLBACK
+/* Iterate over all nodes referenced by parentNodeId by calling the callback
+   function for each child node */                                                        
+typedef UA_StatusCode (*UA_NodeIteratorCallback)(UA_NodeId childId, UA_Boolean isInverse,
+                                                  UA_NodeId referenceTypeId, void *handle);
 #endif
+ 
+UA_StatusCode UA_EXPORT
+UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId,
+                               UA_NodeIteratorCallback callback, void *handle) ;
 
 #ifdef __cplusplus
 } // extern "C"

+ 2 - 5
include/ua_connection.h

@@ -43,9 +43,7 @@ typedef struct UA_SecureChannel UA_SecureChannel;
  * without being aware of the underlying transport technology.
  *
  * Connection Config
- * =================
- **/
-
+ * ================= */
 typedef struct UA_ConnectionConfig {
     UA_UInt32 protocolVersion;
     UA_UInt32 sendBufferSize;
@@ -58,8 +56,7 @@ extern const UA_EXPORT UA_ConnectionConfig UA_ConnectionConfig_standard;
 
 /**
  * Connection Structure
- * ====================
- */
+ * ==================== */
 typedef enum UA_ConnectionState {
     UA_CONNECTION_OPENING,     /* The socket is open, but the HEL/ACK handshake
                                   is not done */

+ 7 - 12
src/client/ua_client_highlevel.c

@@ -253,24 +253,20 @@ UA_Client_call(UA_Client *client, const UA_NodeId objectId, const UA_NodeId meth
 
 UA_StatusCode 
 __UA_Client_writeAttribute(UA_Client *client, UA_NodeId nodeId, UA_AttributeId attributeId,
-                           void *in, const UA_DataType *inDataType) {
-    if(in == NULL)
+                           const void *in, const UA_DataType *inDataType) {
+    if(!in)
       return UA_STATUSCODE_BADTYPEMISMATCH;
     
-    UA_Variant *tmp = (UA_Variant *) in;
-    if (tmp == NULL) return 1;
-    
     UA_WriteRequest *wReq = UA_WriteRequest_new();
     wReq->nodesToWrite = UA_WriteValue_new();
     wReq->nodesToWriteSize = 1;
     UA_NodeId_copy(&nodeId, &wReq->nodesToWrite[0].nodeId);
     wReq->nodesToWrite[0].attributeId = attributeId;
-    if (attributeId == UA_ATTRIBUTEID_VALUE) {
-      UA_Variant_copy((UA_Variant *) in, &wReq->nodesToWrite[0].value.value);
+    if(attributeId == UA_ATTRIBUTEID_VALUE) {
+      UA_Variant_copy((const UA_Variant*)in, &wReq->nodesToWrite[0].value.value);
       wReq->nodesToWrite[0].value.hasValue = true;
-    }
-    else {
-      if( ! UA_Variant_setScalarCopy(&wReq->nodesToWrite[0].value.value, in, inDataType) )
+    } else {
+        UA_Variant_setScalarCopy(&wReq->nodesToWrite[0].value.value, in, inDataType);
         wReq->nodesToWrite[0].value.hasValue = true;
     }
     
@@ -279,7 +275,6 @@ __UA_Client_writeAttribute(UA_Client *client, UA_NodeId nodeId, UA_AttributeId a
     
     UA_WriteRequest_delete(wReq);
     UA_WriteResponse_deleteMembers(&wResp);
-    
     return retval;
 }
 
@@ -326,4 +321,4 @@ __UA_Client_readAttribute(UA_Client *client, UA_NodeId nodeId, UA_AttributeId at
 
     UA_ReadResponse_deleteMembers(&response);
     return retval;
-}
+}

+ 2 - 3
src/client/ua_client_highlevel_subscriptions.c

@@ -91,9 +91,8 @@ UA_StatusCode UA_Client_Subscriptions_remove(UA_Client *client, UA_UInt32 subscr
 UA_StatusCode
 UA_Client_Subscriptions_addMonitoredItem(UA_Client *client, UA_UInt32 subscriptionId,
                                          UA_NodeId nodeId, UA_UInt32 attributeID,
-                                         void (*handlingFunction)(UA_UInt32 handle, UA_DataValue *value, void *context),
-                                         void *handlingContext,
-                                         UA_UInt32 *newMonitoredItemId) {
+                                         UA_MonitoredItemHandlingFunction handlingFunction,
+                                         void *handlingContext, UA_UInt32 *newMonitoredItemId) {
     UA_Client_Subscription *sub;
     LIST_FOREACH(sub, &client->subscriptions, listEntry) {
         if(sub->SubscriptionID == subscriptionId)