Parcourir la source

Merge branch 'dev' of https://github.com/acplt/open62541 into dev

ichrispa il y a 9 ans
Parent
commit
540765f18c

+ 5 - 4
CMakeLists.txt

@@ -283,7 +283,6 @@ option(BUILD_EXAMPLESERVER "Build the example server" OFF)
 if(BUILD_EXAMPLESERVER)
 if(BUILD_EXAMPLESERVER)
     set(server_source $<TARGET_OBJECTS:open62541-object>)
     set(server_source $<TARGET_OBJECTS:open62541-object>)
     add_executable(server_static examples/server.c ${server_source})
     add_executable(server_static examples/server.c ${server_source})
-    add_executable(server_simple examples/server_simple.c ${server_source})
     add_executable(server examples/server.c)
     add_executable(server examples/server.c)
     if(ENABLE_AMALGAMATION)
     if(ENABLE_AMALGAMATION)
        ADD_DEPENDENCIES(server amalgamation) 
        ADD_DEPENDENCIES(server amalgamation) 
@@ -291,16 +290,13 @@ if(BUILD_EXAMPLESERVER)
     target_link_libraries(server open62541)
     target_link_libraries(server open62541)
     if(WIN32)
     if(WIN32)
         target_link_libraries(server_static ws2_32)
         target_link_libraries(server_static ws2_32)
-        target_link_libraries(server_simple ws2_32)
         target_link_libraries(server ws2_32)
         target_link_libraries(server ws2_32)
     else()
     else()
         target_link_libraries(server_static rt)
         target_link_libraries(server_static rt)
-        target_link_libraries(server_simple rt)
         target_link_libraries(server rt)
         target_link_libraries(server rt)
     endif()
     endif()
     if(ENABLE_MULTITHREADING)
     if(ENABLE_MULTITHREADING)
         target_link_libraries(server_static urcu-cds urcu urcu-common pthread)
         target_link_libraries(server_static urcu-cds urcu urcu-common pthread)
-        target_link_libraries(server_simple urcu-cds urcu urcu-common pthread)
         target_link_libraries(server urcu-cds urcu urcu-common pthread)
         target_link_libraries(server urcu-cds urcu urcu-common pthread)
     endif()
     endif()
 endif()
 endif()
@@ -356,6 +352,11 @@ if(BUILD_UNIT_TESTS)
     add_subdirectory(tests)
     add_subdirectory(tests)
 endif()
 endif()
 
 
+option(BUILD_EXAMPLES "Build example servers and clients" OFF)
+if(BUILD_EXAMPLES)
+    add_subdirectory(examples)
+endif()
+
 # build documentation
 # build documentation
 option(BUILD_DOCUMENTATION "Generate doxygen/sphinx documentation" OFF)
 option(BUILD_DOCUMENTATION "Generate doxygen/sphinx documentation" OFF)
 if(BUILD_DOCUMENTATION)
 if(BUILD_DOCUMENTATION)

+ 22 - 0
examples/CMakeLists.txt

@@ -0,0 +1,22 @@
+include_directories(${PROJECT_SOURCE_DIR}/include)
+
+set(LIBS open62541)
+if(NOT WIN32)
+    list(APPEND LIBS rt pthread)
+else()
+    list(APPEND LIBS ws2_32)
+endif()
+if(MULTITHREADING)
+    list(APPEND LIBS urcu-cds urcu urcu-common)
+endif(MULTITHREADING)
+
+add_executable(server_variable server_variable.c)
+target_link_libraries(server_variable ${LIBS})
+
+add_executable(server_repeated_job server_repeated_job.c)
+target_link_libraries(server_repeated_job ${LIBS})
+
+if(ENABLE_METHODCALLS)
+  add_executable(server_method server_method.c)
+  target_link_libraries(server_method ${LIBS})
+endif()

+ 21 - 22
examples/server.c

@@ -261,6 +261,10 @@ int main(int argc, char** argv) {
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Array"), UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(1, DEMOID),
    UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Array"), UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(1, DEMOID),
                            UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
                            UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
 
 
+#define MATRIXID 50003
+   UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Matrix"), UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(1, DEMOID),
+                           UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
+
    UA_UInt32 id = 51000; //running id in namespace 0
    UA_UInt32 id = 51000; //running id in namespace 0
    for(UA_UInt32 type = 0; UA_IS_BUILTIN(type); type++) {
    for(UA_UInt32 type = 0; UA_IS_BUILTIN(type); type++) {
        if(type == UA_TYPES_VARIANT || type == UA_TYPES_DIAGNOSTICINFO)
        if(type == UA_TYPES_VARIANT || type == UA_TYPES_DIAGNOSTICINFO)
@@ -271,37 +275,32 @@ int main(int argc, char** argv) {
         UA_Variant_setScalar(variant, value, &UA_TYPES[type]);
         UA_Variant_setScalar(variant, value, &UA_TYPES[type]);
         char name[15];
         char name[15];
         sprintf(name, "%02d", type);
         sprintf(name, "%02d", type);
-        UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, name);
-        UA_Server_addVariableNode(server, variant, myIntegerName, UA_NODEID_NUMERIC(1, ++id),
+        UA_QualifiedName qualifiedName = UA_QUALIFIEDNAME(1, name);
+        UA_Server_addVariableNode(server, variant, qualifiedName, UA_NODEID_NUMERIC(1, ++id),
                                   UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
                                   UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
 
 
         //add an array node for every built-in type
         //add an array node for every built-in type
         UA_Variant *arrayvar = UA_Variant_new();
         UA_Variant *arrayvar = UA_Variant_new();
         UA_Variant_setArray(arrayvar, UA_Array_new(&UA_TYPES[type], 10), 10, &UA_TYPES[type]);
         UA_Variant_setArray(arrayvar, UA_Array_new(&UA_TYPES[type], 10), 10, &UA_TYPES[type]);
-        UA_Server_addVariableNode(server, arrayvar, myIntegerName, UA_NODEID_NUMERIC(1, ++id),
+        UA_Server_addVariableNode(server, arrayvar, qualifiedName, UA_NODEID_NUMERIC(1, ++id),
                                   UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
                                   UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+
+        //add an matrix node for every built-in type
+        arrayvar = UA_Variant_new();
+        void* myMultiArray = UA_Array_new(&UA_TYPES[type],9);
+        arrayvar->arrayDimensions = UA_Array_new(&UA_TYPES[UA_TYPES_INT32],2);
+        arrayvar->arrayDimensions[0] = 3;
+        arrayvar->arrayDimensions[1] = 3;
+        arrayvar->arrayDimensionsSize = 2;
+        arrayvar->arrayLength = 9;
+        arrayvar->data = myMultiArray;
+        arrayvar->type = &UA_TYPES[type];
+        UA_Server_addVariableNode(server, arrayvar, qualifiedName, UA_NODEID_NUMERIC(1, ++id),
+                                  UA_NODEID_NUMERIC(1, MATRIXID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
    }
    }
 
 
 
 
-   //add a multidimensional Int32 array node for testing purpose
-   void *value = UA_new(&UA_TYPES[UA_TYPES_INT32]);
-   UA_Variant *variant = UA_Variant_new();
-   UA_Variant_setScalar(variant, value, &UA_TYPES[UA_TYPES_INT32]);
-   char myMultiArrayTypename[15];
-   sprintf(myMultiArrayTypename, "%02d", 99);
-   UA_QualifiedName myMultiArrayType = UA_QUALIFIEDNAME(1, myMultiArrayTypename);
-
-   UA_Variant *arrayvar = UA_Variant_new();
-   UA_Int32 *myMultiArray = UA_Array_new(&UA_TYPES[UA_TYPES_INT32],10);
-   arrayvar->arrayDimensions = UA_Array_new(&UA_TYPES[UA_TYPES_INT32],2);
-   arrayvar->arrayDimensions[0] = 2;
-   arrayvar->arrayDimensions[1] = 5;
-   arrayvar->arrayDimensionsSize = 2;
-   arrayvar->arrayLength = 10;
-   arrayvar->data = myMultiArray;
-   arrayvar->type = &UA_TYPES[UA_TYPES_INT32];
-   UA_Server_addVariableNode(server, arrayvar, myMultiArrayType, UA_NODEID_NUMERIC(1, 31415),
-                             UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
+
 
 
 #ifdef ENABLE_METHODCALLS
 #ifdef ENABLE_METHODCALLS
    UA_Argument inputArguments;
    UA_Argument inputArguments;

+ 78 - 0
examples/server_method.c

@@ -0,0 +1,78 @@
+/*
+ * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ */
+
+#include <signal.h>
+#include <stdlib.h>
+
+#ifdef UA_NO_AMALGAMATION
+# include "ua_types.h"
+# include "ua_server.h"
+# include "logger_stdout.h"
+# include "networklayer_tcp.h"
+#else
+# include "open62541.h"
+#endif
+
+UA_Boolean running = UA_TRUE;
+UA_Logger logger;
+
+static UA_StatusCode helloWorldMethod(const UA_NodeId objectId, const UA_Variant *input, 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;
+} 
+
+static void stopHandler(int sign) {
+    UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "received ctrl-c");
+    running = 0;
+}
+
+int main(int argc, char** argv) {
+    signal(SIGINT, stopHandler); /* catches ctrl-c */
+
+    /* initialize the server */
+    UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
+    logger = Logger_Stdout_new();
+    UA_Server_setLogger(server, logger);
+    UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664));
+
+    /* add the method node with the callback */
+    UA_Argument inputArguments;
+    UA_Argument_init(&inputArguments);
+    inputArguments.arrayDimensionsSize = -1;
+    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 = -1;
+    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_Server_addMethodNode(server, UA_QUALIFIEDNAME(1, "hello world"), UA_NODEID_NUMERIC(1,62541),
+                            UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
+                            &helloWorldMethod, 1, &inputArguments, 1, &outputArguments);
+
+    /* start server */
+    UA_StatusCode retval = UA_Server_run(server, 1, &running); //blocks until running=false
+
+    /* ctrl-c received -> clean up */
+    UA_Server_delete(server);
+    return retval;
+}

+ 45 - 0
examples/server_repeated_job.c

@@ -0,0 +1,45 @@
+/*
+ * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ */
+
+#include <signal.h>
+
+#ifdef UA_NO_AMALGAMATION
+# include "ua_types.h"
+# include "ua_server.h"
+# include "logger_stdout.h"
+# include "networklayer_tcp.h"
+#else
+# include "open62541.h"
+#endif
+
+UA_Boolean running = 1;
+UA_Logger logger;
+
+static void stopHandler(int sign) {
+    UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "received ctrl-c");
+    running = 0;
+}
+
+static void testCallback(UA_Server *server, void *data) {
+    UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "testcallback");
+}
+
+int main(int argc, char** argv) {
+    signal(SIGINT, stopHandler); /* catches ctrl-c */
+
+    UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
+    logger = Logger_Stdout_new();
+    UA_Server_setLogger(server, logger);
+    UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664));
+
+    /* add a repeated job to the server */
+    UA_Job job = {.type = UA_JOBTYPE_METHODCALL,
+                  .job.methodCall = {.method = testCallback, .data = NULL} };
+    UA_Server_addRepeatedJob(server, job, 2000, NULL); // call every 2 sec
+
+    UA_StatusCode retval = UA_Server_run(server, 1, &running);
+    UA_Server_delete(server);
+    return retval;
+}

+ 0 - 117
examples/server_simple.c

@@ -1,117 +0,0 @@
-/*
- * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- */
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h> 
-#include <signal.h>
-#include <errno.h> // errno, EINTR
-#include <string.h>
-
-#ifdef UA_NO_AMALGAMATION
-# include "ua_types.h"
-# include "ua_server.h"
-# include "logger_stdout.h"
-# include "networklayer_tcp.h"
-#else
-# include "open62541.h"
-#endif
-
-UA_Boolean running = 1;
-UA_Logger logger;
-
-static void stopHandler(int sign) {
-    printf("Received Ctrl-C\n");
-	running = 0;
-}
-
-static UA_ByteString loadCertificate(void) {
-    UA_ByteString certificate = UA_STRING_NULL;
-	FILE *fp = NULL;
-	//FIXME: a potential bug of locating the certificate, we need to get the path from the server's config
-	fp=fopen("server_cert.der", "rb");
-
-	if(!fp) {
-        errno = 0; // we read errno also from the tcp layer...
-        return certificate;
-    }
-
-    fseek(fp, 0, SEEK_END);
-    certificate.length = ftell(fp);
-    certificate.data = malloc(certificate.length*sizeof(UA_Byte));
-	if(!certificate.data)
-		return certificate;
-
-    fseek(fp, 0, SEEK_SET);
-    if(fread(certificate.data, sizeof(UA_Byte), certificate.length, fp) < (size_t)certificate.length)
-        UA_ByteString_deleteMembers(&certificate); // error reading the cert
-    fclose(fp);
-
-    return certificate;
-}
-
-static void testCallback(UA_Server *server, void *data) {
-    UA_LOG_INFO(logger, UA_LOGCATEGORY_USERLAND, "testcallback");
-}
-
-int main(int argc, char** argv) {
-	signal(SIGINT, stopHandler); /* catches ctrl-c */
-
-	UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
-    logger = Logger_Stdout_new();
-    UA_Server_setLogger(server, logger);
-    UA_ByteString certificate = loadCertificate();
-    UA_Server_setServerCertificate(server, certificate);
-    UA_ByteString_deleteMembers(&certificate);
-    UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664));
-
-    UA_Job job = {.type = UA_JOBTYPE_METHODCALL,
-                  .job.methodCall = {.method = testCallback, .data = NULL} };
-    UA_Server_addRepeatedJob(server, job, 2000, NULL); // call every 2 sec
-
-	// add a variable node to the adresspace
-    UA_Variant *myIntegerVariant = UA_Variant_new();
-    UA_Int32 myInteger = 42;
-    UA_Variant_setScalarCopy(myIntegerVariant, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
-    UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer");
-    UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); /* UA_NODEID_NULL would assign a random free nodeid */
-    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
-    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
-    UA_Server_addVariableNode(server, myIntegerVariant, myIntegerName,
-                              myIntegerNodeId, parentNodeId, parentReferenceNodeId);
-
-/*
-#ifdef BENCHMARK
-    UA_UInt32 nodeCount = 50;
-    char str[32];
-    for(UA_UInt32 i = 0;i<nodeCount;i++) {
-        // scalar
-        void *data = UA_new(&UA_TYPES[i]);
-        UA_Variant *variant = UA_Variant_new();
-        UA_Variant_setScalar(variant, data, &UA_TYPES[i]);
-        sprintf(str,"%d",i);
-        UA_QualifiedName nodeName = UA_QUALIFIEDNAME(1, str);
-        UA_NodeId id = UA_NODEID_NUMERIC(1, 100 + i);
-        UA_Server_addVariableNode(server, variant, nodeName, id,
-                                  UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-                                  UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
-
-        // array
-        data = UA_Array_new(&UA_TYPES[i], 10);
-        variant = UA_Variant_new();
-        UA_Variant_setArray(variant, data, 10, &UA_TYPES[i]);
-        sprintf(str,"array of %d",i);
-        nodeName = UA_QUALIFIEDNAME(1, str);
-        id = UA_NODEID_NUMERIC(1, 200 + i);
-        UA_Server_addVariableNode(server, variant, nodeName, id,
-                                  UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
-                                  UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
-    }
-#endif
-*/
-    UA_StatusCode retval = UA_Server_run(server, 1, &running);
-	UA_Server_delete(server);
-
-	return retval;
-}

+ 48 - 0
examples/server_variable.c

@@ -0,0 +1,48 @@
+/*
+ * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ */
+
+#include <signal.h>
+
+#ifdef UA_NO_AMALGAMATION
+# include "ua_types.h"
+# include "ua_server.h"
+# include "logger_stdout.h"
+# include "networklayer_tcp.h"
+#else
+# include "open62541.h"
+#endif
+
+UA_Boolean running = 1;
+UA_Logger logger;
+
+static void stopHandler(int sign) {
+    UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "received ctrl-c");
+    running = 0;
+}
+
+int main(int argc, char** argv) {
+    signal(SIGINT, stopHandler); /* catches ctrl-c */
+
+    UA_Server *server = UA_Server_new(UA_ServerConfig_standard);
+    logger = Logger_Stdout_new();
+    UA_Server_setLogger(server, logger);
+    UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664));
+
+    /* add a variable node to the adresspace */
+    UA_Variant *myIntegerVariant = UA_Variant_new();
+    UA_Int32 myInteger = 42;
+    UA_Variant_setScalarCopy(myIntegerVariant, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
+    UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer");
+    UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); /* UA_NODEID_NULL would assign a random free nodeid */
+    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
+    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
+    UA_Server_addVariableNode(server, myIntegerVariant, myIntegerName,
+                              myIntegerNodeId, parentNodeId, parentReferenceNodeId);
+
+    UA_StatusCode retval = UA_Server_run(server, 1, &running);
+    UA_Server_delete(server);
+
+    return retval;
+}

+ 1 - 0
include/ua_types.h

@@ -23,6 +23,7 @@ extern "C" {
 #include <stdint.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <stddef.h>
+#include <string.h>
 #include "ua_config.h"
 #include "ua_config.h"
 
 
 /** @brief A two-state logical value (true or false). */
 /** @brief A two-state logical value (true or false). */

+ 1 - 2
src/server/ua_subscription.c

@@ -147,8 +147,7 @@ void Subscription_updateNotifications(UA_Subscription *subscription) {
             changeNotification = UA_malloc(sizeof(UA_DataChangeNotification));
             changeNotification = UA_malloc(sizeof(UA_DataChangeNotification));
 	
 	
             // Create one DataChangeNotification for each queue item held in each monitoredItems queue:
             // Create one DataChangeNotification for each queue item held in each monitoredItems queue:
-            changeNotification->monitoredItems =
-                UA_malloc(sizeof(UA_MonitoredItemNotification) * monItemsChangeT);
+            changeNotification->monitoredItems = UA_Array_new(&UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION], monItemsChangeT);
 	
 	
             // Scan all monitoredItems in this subscription and have their queue transformed into an Array of
             // Scan all monitoredItems in this subscription and have their queue transformed into an Array of
             // the propper NotificationMessageType (Status, Change, Event)
             // the propper NotificationMessageType (Status, Change, Event)