Browse Source

Include code from server_firstSteps.c in documentation (#694)

* Include code from server_firstSteps.c in documentation

* add other tutorials

align other examples with tutorial
Markus Graube 8 years ago
parent
commit
214f2a1cb5

+ 4 - 40
doc/tutorial_client_firstSteps.rst

@@ -34,47 +34,11 @@ Reading a node attibute
 In this example we are going to connect to the server from the second tutorial
 In this example we are going to connect to the server from the second tutorial
 and read the value-attribute of the added variable node.
 and read the value-attribute of the added variable node.
 
 
-.. code-block:: c
-
-    #include <stdio.h>
-    #include "open62541.h"
-
-    int main(int argc, char *argv[])
-    {
-        /* create a client and connect */
-        UA_Client *client = UA_Client_new(UA_ClientConfig_standard);
-        UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:16664");
-        if(retval != UA_STATUSCODE_GOOD) {
-            UA_Client_delete(client);
-            return retval;
-        }
+.. literalinclude:: ../../examples/client_firstSteps.c
+   :language: c
+   :linenos:
+   :lines: 4,5,12,14-
 
 
-        /* create a readrequest with one entry */
-        UA_ReadRequest req;
-        UA_ReadRequest_init(&req);
-        req.nodesToRead = UA_Array_new(1, &UA_TYPES[UA_TYPES_READVALUEID]);
-        req.nodesToReadSize = 1;
-
-        /* define the node and attribute to be read */
-        req.nodesToRead[0].nodeId = UA_NODEID_STRING_ALLOC(1, "the.answer");
-        req.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE;
-
-        /* call the service and print the result */
-        UA_ReadResponse resp = UA_Client_Service_read(client, req);
-        if(resp.responseHeader.serviceResult == UA_STATUSCODE_GOOD &&
-           resp.resultsSize > 0 && resp.results[0].hasValue &&
-           UA_Variant_isScalar(&resp.results[0].value) &&
-            resp.results[0].value.type == &UA_TYPES[UA_TYPES_INT32]) {
-            UA_Int32 *value = (UA_Int32*)resp.results[0].value.data;
-            printf("the value is: %i\n", *value);
-        }
-
-        UA_ReadRequest_deleteMembers(&req);
-        UA_ReadResponse_deleteMembers(&resp);
-        UA_Client_disconnect(client);
-        UA_Client_delete(client);
-        return UA_STATUSCODE_GOOD;
-    }
 
 
 Further tasks
 Further tasks
 -------------
 -------------

+ 4 - 25
doc/tutorial_server_firstSteps.rst

@@ -17,31 +17,10 @@ have the ``open62541.c/.h`` files in the current folder.
 
 
 Now create a new C source-file called ``myServer.c`` with the following content:
 Now create a new C source-file called ``myServer.c`` with the following content:
 
 
-.. code-block:: c
-
-   #include <signal.h>
-   #include "open62541.h"
-
-   UA_Boolean running = true;
-   void signalHandler(int sig) {
-       running = false;
-   }
-
-   int main(void) {
-       signal(SIGINT, signalHandler); /* catch ctrl-c */
-
-       UA_ServerConfig config = UA_ServerConfig_standard;
-       UA_ServerNetworkLayer nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664);
-       config.networkLayers = &nl;
-       config.networkLayersSize = 1;
-
-       UA_Server *server = UA_Server_new(config);
-       UA_Server_run(server, &running);
-       UA_Server_delete(server);
-       nl.deleteMembers(&nl);
-
-       return 0;
-   }
+.. literalinclude:: ../../examples/server_firstSteps.c
+   :language: c
+   :linenos:
+   :lines: 4,12,14-34
 
 
 This is all that is needed for a simple OPC UA server. Compile the the server
 This is all that is needed for a simple OPC UA server. Compile the the server
 with GCC using the following command:
 with GCC using the following command:

+ 11 - 75
doc/tutorial_server_method.rst

@@ -5,82 +5,18 @@ This tutorial demonstrates how to add method nodes to the server. Use an UA
 client, e.g., UaExpert to call the method (right-click on the method node ->
 client, e.g., UaExpert to call the method (right-click on the method node ->
 call).
 call).
 
 
-.. code-block:: c
+The first example shows how to define input and output arguments (lines 72 - 88),
+make the method executable (lines 94,95), add the method node (line 96-101)
+with a specified method callback (lines 10 - 24).
 
 
-    #include <signal.h>
-    #include <stdlib.h>
-    #include "open62541.h"
+The second example shows that a method can also be applied on an array
+as input argument and output argument.
 
 
-    UA_Boolean running = true;
-    static void stopHandler(int sign) {
-        UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "received ctrl-c");
-        running = 0;
-    }
+The last example presents a way to bind a new method callback to an already
+instantiated method node.
 
 
-    UA_Logger logger = UA_Log_Stdout;
 
 
-    static UA_StatusCode
-    helloWorldMethod(void *handle, const UA_NodeId objectId, size_t inputSize,
-                     const UA_Variant *input, size_t outputSize, UA_Variant *output) {
-            UA_String *inputStr = (UA_String*)input->data;
-            UA_String tmp = UA_STRING_ALLOC("Hello ");
-            if(inputStr->length > 0) {
-                tmp.data = realloc(tmp.data, tmp.length + inputStr->length);
-                memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length);
-                tmp.length += inputStr->length;
-            }
-            UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]);
-            UA_String_deleteMembers(&tmp);
-            UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Hello World was called");
-            return UA_STATUSCODE_GOOD;
-    }
-
-    int main(int argc, char** argv) {
-        signal(SIGINT, stopHandler); /* catches ctrl-c */
-
-        /* initialize the server */
-        UA_ServerConfig config = UA_ServerConfig_standard;
-        UA_ServerNetworkLayer nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664);
-        config.networkLayers = &nl;
-        config.networkLayersSize = 1;
-        UA_Server *server = UA_Server_new(config);
-
-        /* add the method node with the callback */
-        UA_Argument inputArguments;
-        UA_Argument_init(&inputArguments);
-        inputArguments.arrayDimensionsSize = 0;
-        inputArguments.arrayDimensions = NULL;
-        inputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
-        inputArguments.description = UA_LOCALIZEDTEXT("en_US", "A String");
-        inputArguments.name = UA_STRING("MyInput");
-        inputArguments.valueRank = -1;
-
-        UA_Argument outputArguments;
-        UA_Argument_init(&outputArguments);
-        outputArguments.arrayDimensionsSize = 0;
-        outputArguments.arrayDimensions = NULL;
-        outputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
-        outputArguments.description = UA_LOCALIZEDTEXT("en_US", "A String");
-        outputArguments.name = UA_STRING("MyOutput");
-        outputArguments.valueRank = -1;
-
-        UA_MethodAttributes helloAttr;
-        UA_MethodAttributes_init(&helloAttr);
-        helloAttr.description = UA_LOCALIZEDTEXT("en_US","Say `Hello World`");
-        helloAttr.displayName = UA_LOCALIZEDTEXT("en_US","Hello World");
-        helloAttr.executable = true;
-        helloAttr.userExecutable = true;
-        UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1,62541),
-                                UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-                                UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
-                                UA_QUALIFIEDNAME(1, "hello world"), 
-                                helloAttr, &helloWorldMethod, NULL,
-                                1, &inputArguments, 1, &outputArguments, NULL);
-
-        /* run the server */
-        UA_Server_run(server, &running);
-        UA_Server_delete(server);
-        nl.deleteMembers(&nl);
-
-        return 0;
-    }
+.. literalinclude:: ../../examples/server_method.c
+   :language: c
+   :linenos:
+   :lines: 4,5,14,16-

+ 15 - 44
doc/tutorial_server_variables.rst

@@ -11,57 +11,18 @@ connected to a physical process in the background. Make sure to read the
 This is the code for a server with a single variable node holding an integer. We
 This is the code for a server with a single variable node holding an integer. We
 will take this example to explain some of the fundamental concepts of open62541.
 will take this example to explain some of the fundamental concepts of open62541.
 
 
-.. code-block:: c
+.. literalinclude:: ../../examples/server_variable.c
+   :language: c
+   :linenos:
+   :lines: 4,13,15-
 
 
-    #include <signal.h>
-    #include "open62541.h"
-
-    UA_Boolean running = true;
-    static void stopHandler(int sign) {
-        running = false;
-    }
-
-    int main(int argc, char** argv) {
-        signal(SIGINT, stopHandler); /* catch ctrl-c */
-
-        UA_ServerConfig config = UA_ServerConfig_standard;
-        UA_ServerNetworkLayer nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664);
-        config.networkLayers = &nl;
-        config.networkLayersSize = 1;
-        UA_Server *server = UA_Server_new(config);
-
-        /* 1) Define the attribute of the myInteger variable node */
-        UA_VariableAttributes attr;
-        UA_VariableAttributes_init(&attr);
-        UA_Int32 myInteger = 42;
-        UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
-        attr.description = UA_LOCALIZEDTEXT("en_US","the answer");
-        attr.displayName = UA_LOCALIZEDTEXT("en_US","the answer");
-
-        /* 2) Add the variable node to the information model */
-        UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer");
-        UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer");
-        UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
-        UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
-        UA_StatusCode retval = UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId,
-                                                         parentReferenceNodeId, myIntegerName,
-                                                         UA_NODEID_NULL, attr, NULL, NULL);
-
-        if(retval == UA_STATUSCODE_GOOD)
-            UA_Server_run(server, &running);
-
-        UA_Server_delete(server);
-        nl.deleteMembers(&nl);
-
-        return retval;
-    }
 
 
 Variants and Datatypes
 Variants and Datatypes
 ----------------------
 ----------------------
 
 
 The datatype *variant* belongs to the built-in datatypes of OPC UA and is used
 The datatype *variant* belongs to the built-in datatypes of OPC UA and is used
 as a container type. A variant can hold any other datatype as a scalar (except
 as a container type. A variant can hold any other datatype as a scalar (except
-Variant) or as an array. Array variants can additionally denote the
+variant) or as an array. Array variants can additionally denote the
 dimensionality of the data (e.g. a 2x3 matrix) in an additional integer array.
 dimensionality of the data (e.g. a 2x3 matrix) in an additional integer array.
 You can find the code that defines the variant datatype :ref:`here <variant>`.
 You can find the code that defines the variant datatype :ref:`here <variant>`.
 
 
@@ -133,6 +94,10 @@ some examples for their usage.
    UA_NodeId id3 = UA_NODEID_STRING_ALLOC(1, "testid");
    UA_NodeId id3 = UA_NODEID_STRING_ALLOC(1, "testid");
    UA_NodeId_deleteMembers(&id3); /* free the allocated string */
    UA_NodeId_deleteMembers(&id3); /* free the allocated string */
 
 
+
+What is UA_NODEID_STRING_ALLOC for?
+
+
 Adding a variable node to the server that contains a user-defined callback
 Adding a variable node to the server that contains a user-defined callback
 --------------------------------------------------------------------------
 --------------------------------------------------------------------------
 
 
@@ -143,6 +108,12 @@ callback pointer is intserted into the node.
 Consider ``examples/server_datasource.c`` in the repository. The examples are
 Consider ``examples/server_datasource.c`` in the repository. The examples are
 compiled if the Cmake option UA_BUILD_EXAMPLE is turned on.
 compiled if the Cmake option UA_BUILD_EXAMPLE is turned on.
 
 
+
+UA_Server_addVariableNode vs. UA_Server_addDataSourceVariableNode
+UA_ValueCallback
+UA_DataSource
+
+
 Asserting success/failure
 Asserting success/failure
 -------------------------
 -------------------------
 
 

+ 10 - 5
examples/client_firstSteps.c

@@ -5,11 +5,11 @@
 #include <inttypes.h>
 #include <inttypes.h>
 
 
 #ifdef UA_NO_AMALGAMATION
 #ifdef UA_NO_AMALGAMATION
-# include "ua_client.h"
-# include "ua_config_standard.h"
-# include "ua_network_tcp.h"
+#include "ua_client.h"
+#include "ua_config_standard.h"
+#include "ua_network_tcp.h"
 #else
 #else
-# include "open62541.h"
+#include "open62541.h"
 #endif
 #endif
 
 
 int main(void) {
 int main(void) {
@@ -24,13 +24,18 @@ int main(void) {
     UA_DateTime raw_date = 0;
     UA_DateTime raw_date = 0;
     UA_String string_date;
     UA_String string_date;
 
 
+    /* create a readrequest with one entry */
     UA_ReadRequest rReq;
     UA_ReadRequest rReq;
     UA_ReadRequest_init(&rReq);
     UA_ReadRequest_init(&rReq);
     rReq.nodesToRead = UA_Array_new(1, &UA_TYPES[UA_TYPES_READVALUEID]);
     rReq.nodesToRead = UA_Array_new(1, &UA_TYPES[UA_TYPES_READVALUEID]);
     rReq.nodesToReadSize = 1;
     rReq.nodesToReadSize = 1;
-    rReq.nodesToRead[0].nodeId = UA_NODEID_NUMERIC(0, 2258);
+
+    /* define the node and attribute to be read */
+    #define NS0_CURRENT_TIME 2258
+    rReq.nodesToRead[0].nodeId = UA_NODEID_NUMERIC(0, NS0_CURRENT_TIME);
     rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE;
     rReq.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE;
 
 
+    /* call the service and print the result */
     UA_ReadResponse rResp = UA_Client_Service_read(client, rReq);
     UA_ReadResponse rResp = UA_Client_Service_read(client, rReq);
     if(rResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD && rResp.resultsSize > 0 &&
     if(rResp.responseHeader.serviceResult == UA_STATUSCODE_GOOD && rResp.resultsSize > 0 &&
        rResp.results[0].hasValue && UA_Variant_isScalar(&rResp.results[0].value) &&
        rResp.results[0].hasValue && UA_Variant_isScalar(&rResp.results[0].value) &&

+ 5 - 6
examples/server_firstSteps.c

@@ -1,16 +1,15 @@
 /* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
 /* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
  * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
  * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
 
 
-#include <stdio.h>
 #include <signal.h>
 #include <signal.h>
 
 
 #ifdef UA_NO_AMALGAMATION
 #ifdef UA_NO_AMALGAMATION
-# include "ua_types.h"
-# include "ua_server.h"
-# include "ua_config_standard.h"
-# include "ua_network_tcp.h"
+#include "ua_types.h"
+#include "ua_server.h"
+#include "ua_config_standard.h"
+#include "ua_network_tcp.h"
 #else
 #else
-# include "open62541.h"
+#include "open62541.h"
 #endif
 #endif
 
 
 UA_Boolean running = true;
 UA_Boolean running = true;

+ 75 - 57
examples/server_method.c

@@ -5,18 +5,20 @@
 #include <stdlib.h>
 #include <stdlib.h>
 
 
 #ifdef UA_NO_AMALGAMATION
 #ifdef UA_NO_AMALGAMATION
-# include "ua_types.h"
-# include "ua_server.h"
-# include "ua_config_standard.h"
-# include "ua_network_tcp.h"
-# include "ua_log_stdout.h"
+#include "ua_types.h"
+#include "ua_server.h"
+#include "ua_config_standard.h"
+#include "ua_network_tcp.h"
+#include "ua_log_stdout.h"
 #else
 #else
-# include "open62541.h"
+#include "open62541.h"
 #endif
 #endif
 
 
 UA_Boolean running = true;
 UA_Boolean running = true;
 UA_Logger logger = UA_Log_Stdout;
 UA_Logger logger = UA_Log_Stdout;
 
 
+
+// EXAMPLE 1 method
 static UA_StatusCode
 static UA_StatusCode
 helloWorldMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input,
 helloWorldMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input,
                  size_t outputSize, UA_Variant *output) {
                  size_t outputSize, UA_Variant *output) {
@@ -33,6 +35,18 @@ helloWorldMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const
         return UA_STATUSCODE_GOOD;
         return UA_STATUSCODE_GOOD;
 }
 }
 
 
+// EXAMPLE 2 method
+static UA_StatusCode
+IncInt32ArrayValuesMethod(void *handle, const UA_NodeId objectId, size_t inputSize,
+                          const UA_Variant *input, size_t outputSize, UA_Variant *output) {
+    UA_Variant_setArrayCopy(output, input->data, 5, &UA_TYPES[UA_TYPES_INT32]);
+    for(size_t i = 0; i< input->arrayLength; i++)
+        ((UA_Int32*)output->data)[i] = ((UA_Int32*)input->data)[i] + 1;
+    return UA_STATUSCODE_GOOD;
+}
+
+
+// EXAMPLE 3 method
 static UA_StatusCode
 static UA_StatusCode
 fooBarMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input,
 fooBarMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input,
                  size_t outputSize, UA_Variant *output) {
                  size_t outputSize, UA_Variant *output) {
@@ -46,19 +60,10 @@ fooBarMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_
         }
         }
         UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]);
         UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]);
         UA_String_deleteMembers(&tmp);
         UA_String_deleteMembers(&tmp);
-        UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Hello World was called");
+        UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "FooBar was called");
         return UA_STATUSCODE_GOOD;
         return UA_STATUSCODE_GOOD;
 }
 }
 
 
-static UA_StatusCode
-IncInt32ArrayValuesMethod(void *handle, const UA_NodeId objectId, size_t inputSize,
-                          const UA_Variant *input, size_t outputSize, UA_Variant *output) {
-    UA_Variant_setArrayCopy(output, input->data, 5, &UA_TYPES[UA_TYPES_INT32]);
-    for(size_t i = 0; i< input->arrayLength; i++)
-        ((UA_Int32*)output->data)[i] = ((UA_Int32*)input->data)[i] + 1;
-    return UA_STATUSCODE_GOOD;
-}
-
 static void stopHandler(int sign) {
 static void stopHandler(int sign) {
     UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "received ctrl-c");
     UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "received ctrl-c");
     running = 0;
     running = 0;
@@ -76,23 +81,23 @@ int main(int argc, char** argv) {
 
 
     //EXAMPLE 1
     //EXAMPLE 1
     /* add the method node with the callback */
     /* add the method node with the callback */
-    UA_Argument inputArguments;
-    UA_Argument_init(&inputArguments);
-    inputArguments.arrayDimensionsSize = 0;
-    inputArguments.arrayDimensions = NULL;
-    inputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
-    inputArguments.description = UA_LOCALIZEDTEXT("en_US", "A String");
-    inputArguments.name = UA_STRING("MyInput");
-    inputArguments.valueRank = -1;
-
-    UA_Argument outputArguments;
-    UA_Argument_init(&outputArguments);
-    outputArguments.arrayDimensionsSize = 0;
-    outputArguments.arrayDimensions = NULL;
-    outputArguments.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
-    outputArguments.description = UA_LOCALIZEDTEXT("en_US", "A String");
-    outputArguments.name = UA_STRING("MyOutput");
-    outputArguments.valueRank = -1;
+    UA_Argument inputArguments1;
+    UA_Argument_init(&inputArguments1);
+    inputArguments1.arrayDimensionsSize = 0;
+    inputArguments1.arrayDimensions = NULL;
+    inputArguments1.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
+    inputArguments1.description = UA_LOCALIZEDTEXT("en_US", "A String");
+    inputArguments1.name = UA_STRING("MyInput");
+    inputArguments1.valueRank = -1;
+
+    UA_Argument outputArguments1;
+    UA_Argument_init(&outputArguments1);
+    outputArguments1.arrayDimensionsSize = 0;
+    outputArguments1.arrayDimensions = NULL;
+    outputArguments1.dataType = UA_TYPES[UA_TYPES_STRING].typeId;
+    outputArguments1.description = UA_LOCALIZEDTEXT("en_US", "A String");
+    outputArguments1.name = UA_STRING("MyOutput");
+    outputArguments1.valueRank = -1;
 
 
     UA_MethodAttributes helloAttr;
     UA_MethodAttributes helloAttr;
     UA_MethodAttributes_init(&helloAttr);
     UA_MethodAttributes_init(&helloAttr);
@@ -103,36 +108,37 @@ int main(int argc, char** argv) {
     UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1,62541),
     UA_Server_addMethodNode(server, UA_NODEID_NUMERIC(1,62541),
                             UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                             UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                             UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
                             UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
-                            UA_QUALIFIEDNAME(1, "hello world"), 
+                            UA_QUALIFIEDNAME(1, "hello world"),
                             helloAttr, &helloWorldMethod, NULL,
                             helloAttr, &helloWorldMethod, NULL,
-                            1, &inputArguments, 1, &outputArguments, NULL);
-
+                            1, &inputArguments1, 1, &outputArguments1, NULL);
     //END OF EXAMPLE 1
     //END OF EXAMPLE 1
 
 
     //EXAMPLE 2
     //EXAMPLE 2
     /* add another method node: output argument as 1d Int32 array*/
     /* add another method node: output argument as 1d Int32 array*/
     // define input arguments
     // define input arguments
-    UA_Argument_init(&inputArguments);
-    inputArguments.arrayDimensionsSize = 1;
+    UA_Argument inputArguments2;
+    UA_Argument_init(&inputArguments2);
+    inputArguments2.arrayDimensionsSize = 1;
     UA_UInt32 * pInputDimensions = UA_UInt32_new();
     UA_UInt32 * pInputDimensions = UA_UInt32_new();
     pInputDimensions[0] = 5;
     pInputDimensions[0] = 5;
-    inputArguments.arrayDimensions = pInputDimensions;
-    inputArguments.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
-    inputArguments.description = UA_LOCALIZEDTEXT("en_US",
+    inputArguments2.arrayDimensions = pInputDimensions;
+    inputArguments2.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
+    inputArguments2.description = UA_LOCALIZEDTEXT("en_US",
                     "input an array with 5 elements, type int32");
                     "input an array with 5 elements, type int32");
-    inputArguments.name = UA_STRING("int32 value");
-    inputArguments.valueRank = 1;
+    inputArguments2.name = UA_STRING("int32 value");
+    inputArguments2.valueRank = 1;
 
 
     // define output arguments
     // define output arguments
-    UA_Argument_init(&outputArguments);
-    outputArguments.arrayDimensionsSize = 1;
+    UA_Argument outputArguments2;
+    UA_Argument_init(&outputArguments2);
+    outputArguments2.arrayDimensionsSize = 1;
     UA_UInt32 * pOutputDimensions = UA_UInt32_new();
     UA_UInt32 * pOutputDimensions = UA_UInt32_new();
     pOutputDimensions[0] = 5;
     pOutputDimensions[0] = 5;
-    outputArguments.arrayDimensions = pOutputDimensions;
-    outputArguments.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
-    outputArguments.description = UA_LOCALIZEDTEXT("en_US", "increment each array index");
-    outputArguments.name = UA_STRING("output is the array, each index is incremented by one");
-    outputArguments.valueRank = 1;
+    outputArguments2.arrayDimensions = pOutputDimensions;
+    outputArguments2.dataType = UA_TYPES[UA_TYPES_INT32].typeId;
+    outputArguments2.description = UA_LOCALIZEDTEXT("en_US", "increment each array index");
+    outputArguments2.name = UA_STRING("output is the array, each index is incremented by one");
+    outputArguments2.valueRank = 1;
 
 
     UA_MethodAttributes incAttr;
     UA_MethodAttributes incAttr;
     UA_MethodAttributes_init(&incAttr);
     UA_MethodAttributes_init(&incAttr);
@@ -142,18 +148,30 @@ int main(int argc, char** argv) {
     incAttr.userExecutable = true;
     incAttr.userExecutable = true;
     UA_Server_addMethodNode(server, UA_NODEID_STRING(1, "IncInt32ArrayValues"),
     UA_Server_addMethodNode(server, UA_NODEID_STRING(1, "IncInt32ArrayValues"),
                             UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                             UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-                            UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), 
+                            UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                             UA_QUALIFIEDNAME(1, "IncInt32ArrayValues"),
                             UA_QUALIFIEDNAME(1, "IncInt32ArrayValues"),
                             incAttr, &IncInt32ArrayValuesMethod, NULL,
                             incAttr, &IncInt32ArrayValuesMethod, NULL,
-                            1, &inputArguments, 1, &outputArguments, NULL);
+                            1, &inputArguments2, 1, &outputArguments2, NULL);
     //END OF EXAMPLE 2
     //END OF EXAMPLE 2
 
 
-    /* If out methodnode is part of an instantiated object, we never had
-       the opportunity to define the callback... we could do that now
-    */
-    UA_Server_setMethodNode_callback(server, UA_NODEID_NUMERIC(1,62541), &fooBarMethod, NULL);
-
+    //EXAMPLE 3
+    UA_MethodAttributes method3Attr;
+    UA_MethodAttributes_init(&method3Attr);
+    method3Attr.description = UA_LOCALIZEDTEXT("en_US","FooBar");
+    method3Attr.displayName = UA_LOCALIZEDTEXT("en_US","FooBar");
+    method3Attr.executable = true;
+    method3Attr.userExecutable = true;
+    UA_Server_addMethodNode(server, UA_NODEID_STRING(1,"FooBar"),
+                            UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                            UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+                            UA_QUALIFIEDNAME(1, "FooBar"),
+                            method3Attr, NULL, NULL,
+                            1, &inputArguments1, 1, &outputArguments1, NULL);
+    /*  If the method node has no callback (because it was instantiated without one) or
+        if we just want to change it, this can be done with UA_Server_setMethodNode_callback() */
+    UA_Server_setMethodNode_callback(server,  UA_NODEID_NUMERIC(1,62542), &fooBarMethod, NULL);
     //END OF EXAMPLE 3
     //END OF EXAMPLE 3
+
     /* start server */
     /* start server */
     UA_StatusCode retval = UA_Server_run(server, &running);
     UA_StatusCode retval = UA_Server_run(server, &running);
 
 

+ 13 - 11
examples/server_variable.c

@@ -4,13 +4,13 @@
 #include <signal.h>
 #include <signal.h>
 
 
 #ifdef UA_NO_AMALGAMATION
 #ifdef UA_NO_AMALGAMATION
-# include "ua_types.h"
-# include "ua_server.h"
-# include "ua_config_standard.h"
-# include "ua_network_tcp.h"
-# include "ua_log_stdout.h"
+#include "ua_types.h"
+#include "ua_server.h"
+#include "ua_config_standard.h"
+#include "ua_network_tcp.h"
+#include "ua_log_stdout.h"
 #else
 #else
-# include "open62541.h"
+#include "open62541.h"
 #endif
 #endif
 
 
 UA_Boolean running = true;
 UA_Boolean running = true;
@@ -38,13 +38,15 @@ int main(int argc, char** argv) {
     config.networkLayersSize = 1;
     config.networkLayersSize = 1;
     UA_Server *server = UA_Server_new(config);
     UA_Server *server = UA_Server_new(config);
 
 
-    /* add a variable node to the address space */
+    /* 1) Define the attribute of the myInteger variable node */
     UA_VariableAttributes attr;
     UA_VariableAttributes attr;
     UA_VariableAttributes_init(&attr);
     UA_VariableAttributes_init(&attr);
-    /* UA_Int32 myInteger = 42; */
-    /* UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]); */
-    /* attr.description = UA_LOCALIZEDTEXT("en_US","the answer"); */
-    /* attr.displayName = UA_LOCALIZEDTEXT("en_US","the answer"); */
+    UA_Int32 myInteger = 42;
+    UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
+    attr.description = UA_LOCALIZEDTEXT("en_US","the answer");
+    attr.displayName = UA_LOCALIZEDTEXT("en_US","the answer");
+
+    /* 2) Add the variable node to the information model */
     UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer");
     UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer");
     UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer");
     UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer");
     UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
     UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);