Browse Source

generate tutorial docs from compilable c-files

Julius Pfrommer 8 years ago
parent
commit
94c30b74ca

+ 3 - 0
CMakeLists.txt

@@ -352,6 +352,9 @@ add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/open62541.c
                            ${OPEN62541_VER_COMMIT} ${CMAKE_CURRENT_BINARY_DIR}/open62541.c ${internal_headers} ${lib_sources}
                    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/amalgamate.py ${internal_headers} ${lib_sources})
 
+ADD_CUSTOM_TARGET(open625451_amalgamation DEPENDS ${PROJECT_BINARY_DIR}/open62541.h
+                                                  ${PROJECT_BINARY_DIR}/open62541.c)
+
 # example information model from nodeset xml
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/nodeset.h ${PROJECT_BINARY_DIR}/src_generated/nodeset.c
                   PRE_BUILD

+ 10 - 9
doc/CMakeLists.txt

@@ -10,23 +10,15 @@ file(GLOB DOC_SRC "${PROJECT_SOURCE_DIR}/doc/*")
 list(REMOVE_ITEM DOC_SRC "${PROJECT_SOURCE_DIR}/doc/conf.py")
 list(REMOVE_ITEM DOC_SRC "${PROJECT_SOURCE_DIR}/doc/tutorial_server_variables.rst")
 list(REMOVE_ITEM DOC_SRC "${PROJECT_SOURCE_DIR}/doc/tutorial_server_method.rst")
-list(REMOVE_ITEM DOC_SRC "${PROJECT_SOURCE_DIR}/doc/tutorial_server_firstSteps.rst")
-list(REMOVE_ITEM DOC_SRC "${PROJECT_SOURCE_DIR}/doc/tutorial_client_firstSteps.rst")
 file(COPY ${DOC_SRC} DESTINATION ${DOC_SRC_DIR})
 configure_file("${PROJECT_SOURCE_DIR}/doc/conf.py" "${DOC_SRC_DIR}/conf.py")
 configure_file("${PROJECT_SOURCE_DIR}/doc/tutorial_server_variables.rst"
                "${DOC_SRC_DIR}/tutorial_server_variables.rst")
 configure_file("${PROJECT_SOURCE_DIR}/doc/tutorial_server_method.rst"
                "${DOC_SRC_DIR}/tutorial_server_method.rst")
-configure_file("${PROJECT_SOURCE_DIR}/doc/tutorial_server_firstSteps.rst"
-               "${DOC_SRC_DIR}/tutorial_server_firstSteps.rst")
-configure_file("${PROJECT_SOURCE_DIR}/doc/tutorial_client_firstSteps.rst"
-               "${DOC_SRC_DIR}/tutorial_client_firstSteps.rst")
 
 # Copy example code
-set(EXAMPLES ${PROJECT_SOURCE_DIR}/examples/client_firstSteps.c
-             ${PROJECT_SOURCE_DIR}/examples/server_firstSteps.c
-             ${PROJECT_SOURCE_DIR}/examples/server_variable.c
+set(EXAMPLES ${PROJECT_SOURCE_DIR}/examples/server_variable.c
              ${PROJECT_SOURCE_DIR}/examples/server_method.c)
 file(COPY ${EXAMPLES} DESTINATION ${DOC_SRC_DIR})
                
@@ -47,6 +39,11 @@ generate_rst(${PROJECT_SOURCE_DIR}/src/server/ua_services.h ${DOC_SRC_DIR}/servi
 generate_rst(${PROJECT_SOURCE_DIR}/src/server/ua_nodestore.h ${DOC_SRC_DIR}/nodestore.rst)
 generate_rst(${PROJECT_SOURCE_DIR}/src/server/ua_nodes.h ${DOC_SRC_DIR}/information_modelling.rst)
 
+generate_rst(${PROJECT_SOURCE_DIR}/examples/tutorials/client_firststeps.c
+             ${DOC_SRC_DIR}/tutorial_client_firststeps.rst)
+generate_rst(${PROJECT_SOURCE_DIR}/examples/tutorials/server_firststeps.c
+             ${DOC_SRC_DIR}/tutorial_server_firststeps.rst)
+
 add_custom_target(doc_latex ${SPHINX_EXECUTABLE}
   -b latex "${DOC_SRC_DIR}" "${DOC_LATEX_DIR}"
   DEPENDS ${DOC_SRC_DIR}/types.rst ${DOC_SRC_DIR}/constants.rst ${DOC_SRC_DIR}/types_generated.rst
@@ -54,6 +51,8 @@ add_custom_target(doc_latex ${SPHINX_EXECUTABLE}
           ${DOC_SRC_DIR}/log.rst ${DOC_SRC_DIR}/connection.rst ${DOC_SRC_DIR}/services.rst
           ${DOC_SRC_DIR}/nodestore.rst ${DOC_SRC_DIR}/information_modelling.rst
           ${DOC_SRC_DIR}/protocol.rst
+          ${DOC_SRC_DIR}/tutorial_server_firststeps.rst
+          ${DOC_SRC_DIR}/tutorial_client_firststeps.rst
   COMMENT "Building LaTeX sources for documentation with Sphinx")
 add_dependencies(doc_latex open62541)
 
@@ -72,5 +71,7 @@ add_custom_target(doc ${SPHINX_EXECUTABLE}
           ${DOC_SRC_DIR}/log.rst ${DOC_SRC_DIR}/connection.rst ${DOC_SRC_DIR}/services.rst
           ${DOC_SRC_DIR}/nodestore.rst ${DOC_SRC_DIR}/information_modelling.rst
           ${DOC_SRC_DIR}/protocol.rst
+          ${DOC_SRC_DIR}/tutorial_server_firststeps.rst
+          ${DOC_SRC_DIR}/tutorial_client_firststeps.rst
   COMMENT "Building HTML documentation with Sphinx")
 add_dependencies(doc open62541)

+ 0 - 28
doc/tutorial_client_firstSteps.rst

@@ -1,28 +0,0 @@
-Building a simple client
-------------------------
-
-You should already have a basic server from the previous tutorials. open62541
-provides both a server- and clientside API, so creating a client is as easy as
-creating a server. Copy the following into a file `myClient.c`:
-
-.. literalinclude:: client_firstSteps.c
-   :language: c
-   :linenos:
-   :lines: 4,5,14,17-
-
-Compilation is similar to the server example.
-
-.. code-block:: bash
-
-   $ gcc -std=c99 open6251.c myClient.c -o myClient
-
-Further tasks
-^^^^^^^^^^^^^
-* Try to connect to some other OPC UA server by changing
-  ``opc.tcp://localhost:16664`` to an appropriate address (remember that the
-  queried node is contained in any OPC UA server).
-* Try to set the value of the variable node (ns=1,i="the.answer") containing an
-  ``Int32`` from the example server (which is built in
-  :doc:`tutorial_server_firstSteps`) using "UA_Client_write" function. The
-  example server needs some more modifications, i.e., changing request types.
-  The answer can be found in "examples/exampleClient.c".

+ 0 - 43
doc/tutorial_server_firstSteps.rst

@@ -1,43 +0,0 @@
-Building a simple server
-------------------------
-
-This series of tutorial guide you through your first steps with open62541. For
-compiling the examples, you need a compiler (MS Visual Studio 2015 or newer,
-GCC, Clang and MinGW32 are all known to be working). The compilation
-instructions are given for GCC but should be straightforward to adapt.
-
-It will also be very helpful to install an OPC UA Client with a graphical
-frontend, such as UAExpert by Unified Automation. That will enable you to
-examine the information model of any OPC UA server.
-
-To get started, downdload the open62541 single-file release from
-http://open62541.org or generate it according to the :ref:`build instructions
-<building>` with the "amalgamation" option enabled. From now on, we assume you
-have the ``open62541.c/.h`` files in the current folder.
-
-Now create a new C source-file called ``myServer.c`` with the following content:
-
-.. literalinclude:: server_firstSteps.c
-   :language: c
-   :linenos:
-   :lines: 4,12,14-
-
-This is all that is needed for a simple OPC UA server. Compile the the server
-with GCC using the following command:
-
-.. code-block:: bash
-
-   $ gcc -std=c99 open62541.c myServer.c -o myServer
-
-Now start the server (and stop with ctrl-c):
-
-.. code-block:: bash
-
-   $ ./myServer
-
-You have now compiled and run your first OPC UA server. You can go ahead and
-browse the information model with UA Expert. The server will be listening on
-``opc.tcp://localhost:16664`` - go ahead and give it a try.
-
-In the following tutorials, you will be shown how to populate the server's
-information model and how to create a client application.

+ 2 - 2
doc/tutorials.rst

@@ -3,8 +3,8 @@ Tutorials
 
 .. toctree::
 
-   tutorial_server_firstSteps.rst
+   tutorial_server_firststeps.rst
    tutorial_server_variables.rst
    tutorial_server_method.rst
    tutorial_noderelations.rst
-   tutorial_client_firstSteps.rst
+   tutorial_client_firststeps.rst

+ 9 - 6
examples/CMakeLists.txt

@@ -1,5 +1,6 @@
 include_directories(${PROJECT_SOURCE_DIR}/include)
 include_directories(${PROJECT_SOURCE_DIR}/plugins)
+include_directories(${PROJECT_BINARY_DIR})
 
 if(UA_ENABLE_AMALGAMATION)
     include_directories(${PROJECT_BINARY_DIR}) # contain open62541.h
@@ -27,6 +28,10 @@ endif(UA_ENABLE_MULTITHREADING)
 add_executable(server server.c $<TARGET_OBJECTS:open62541-object>)
 target_link_libraries(server ${LIBS})
 
+add_executable(server_firststeps tutorials/server_firststeps.c $<TARGET_OBJECTS:open62541-object>)
+add_dependencies(server_firststeps open625451_amalgamation)
+target_link_libraries(server_firststeps ${LIBS})
+
 if(UA_ENABLE_NONSTANDARD_UDP)
   add_executable(server_udp server_udp.c $<TARGET_OBJECTS:open62541-object> ${PROJECT_SOURCE_DIR}/plugins/ua_network_udp.c)
   target_link_libraries(server_udp ${LIBS})
@@ -39,6 +44,10 @@ endif()
 add_executable(client client.c $<TARGET_OBJECTS:open62541-object>)
 target_link_libraries(client ${LIBS})
 
+add_executable(client_firststeps tutorials/client_firststeps.c $<TARGET_OBJECTS:open62541-object>)
+add_dependencies(client_firststeps open625451_amalgamation)
+target_link_libraries(client_firststeps ${LIBS})
+
 ####################
 # Feature Examples #
 ####################
@@ -52,12 +61,6 @@ target_link_libraries(server_mainloop ${LIBS})
 add_executable(server_datasource server_datasource.c $<TARGET_OBJECTS:open62541-object>)
 target_link_libraries(server_datasource ${LIBS})
 
-add_executable(server_firstSteps server_firstSteps.c $<TARGET_OBJECTS:open62541-object>)
-target_link_libraries(server_firstSteps ${LIBS})
-
-add_executable(client_firstSteps client_firstSteps.c $<TARGET_OBJECTS:open62541-object>)
-target_link_libraries(client_firstSteps ${LIBS})
-
 add_executable(server_instantiation server_instantiation.c $<TARGET_OBJECTS:open62541-object>)
 target_link_libraries(server_instantiation ${LIBS})
 

+ 0 - 35
examples/server_firstSteps.c

@@ -1,35 +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 <signal.h>
-
-#ifdef UA_NO_AMALGAMATION
-#include "ua_types.h"
-#include "ua_server.h"
-#include "ua_config_standard.h"
-#include "ua_network_tcp.h"
-#else
-#include "open62541.h"
-#endif
-
-UA_Boolean running = true;
-static void stopHandler(int sig) {
-    running = false;
-}
-
-int main(void) {
-    signal(SIGINT,  stopHandler);
-    signal(SIGTERM, stopHandler);
-
-    UA_ServerConfig config = UA_ServerConfig_standard;
-    UA_ServerNetworkLayer nl;
-    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;
-}

+ 31 - 10
examples/client_firstSteps.c

@@ -1,19 +1,19 @@
 /* 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 <stdio.h>
-#include <inttypes.h>
+/**
+ * Building a simple client
+ * ------------------------
 
-#ifdef UA_NO_AMALGAMATION
-#include "ua_client.h"
-#include "ua_config_standard.h"
-#else
+ * You should already have a basic server from the previous tutorials. open62541
+ * provides both a server- and clientside API, so creating a client is as easy as
+ * creating a server. Copy the following into a file `myClient.c`: */
+#include <stdio.h>
 #include "open62541.h"
-#endif
 
 int main(void) {
     UA_Client *client = UA_Client_new(UA_ClientConfig_standard);
-    UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:16664");
+    UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
     if(retval != UA_STATUSCODE_GOOD) {
         UA_Client_delete(client);
         return (int)retval;
@@ -24,8 +24,9 @@ int main(void) {
     UA_Variant value; /* Variants can hold scalar values and arrays of any type */
     UA_Variant_init(&value);
 
-    #define NS0_CURRENT_TIME 2258
-    const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, NS0_CURRENT_TIME);
+    /* NodeId of the variable holding the current time */
+    const UA_NodeId nodeId =
+        UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
 
     retval = UA_Client_readValueAttribute(client, nodeId, &value);
     if(retval == UA_STATUSCODE_GOOD &&
@@ -41,3 +42,23 @@ int main(void) {
     UA_Client_delete(client); /* Disconnects the client internally */
     return UA_STATUSCODE_GOOD;
 }
+
+/**
+ * Compilation is similar to the server example.
+ *
+ * .. code-block:: bash
+ *
+ *     $ gcc -std=c99 open6251.c myClient.c -o myClient
+ *
+ * Further tasks
+ * ^^^^^^^^^^^^^
+ *
+ * - Try to connect to some other OPC UA server by changing
+ *   ``opc.tcp://localhost:16664`` to an appropriate address (remember that the
+ *   queried node is contained in any OPC UA server).
+ *
+ * - Try to set the value of the variable node (ns=1,i="the.answer") containing
+ *   an ``Int32`` from the example server (which is built in
+ *   :doc:`tutorial_server_firststeps`) using "UA_Client_write" function. The
+ *   example server needs some more modifications, i.e., changing request types.
+ *   The answer can be found in "examples/exampleClient.c". */

+ 69 - 0
examples/tutorials/server_firststeps.c

@@ -0,0 +1,69 @@
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
+
+/**
+ * Building a simple server
+ * ------------------------
+ *
+ * This series of tutorial guide you through your first steps with open62541.
+ * For compiling the examples, you need a compiler (MS Visual Studio 2015 or
+ * newer, GCC, Clang and MinGW32 are all known to be working). The compilation
+ * instructions are given for GCC but should be straightforward to adapt.
+ *
+ * It will also be very helpful to install an OPC UA Client with a graphical
+ * frontend, such as UAExpert by Unified Automation. That will enable you to
+ * examine the information model of any OPC UA server.
+ *
+ * To get started, downdload the open62541 single-file release from
+ * http://open62541.org or generate it according to the :ref:`build instructions
+ * <building>` with the "amalgamation" option enabled. From now on, we assume
+ * you have the ``open62541.c/.h`` files in the current folder.
+ *
+ * Now create a new C source-file called ``myServer.c`` with the following content: */
+
+#include <signal.h>
+#include "open62541.h"
+
+UA_Boolean running = true;
+static void stopHandler(int sig) {
+    running = false;
+}
+
+int main(void) {
+    signal(SIGINT, stopHandler);
+    signal(SIGTERM, stopHandler);
+
+    UA_ServerConfig config = UA_ServerConfig_standard;
+    UA_ServerNetworkLayer nl;
+    nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 4840);
+    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;
+}
+
+/**
+ * This is all that is needed for a simple OPC UA server. Compile the the server
+ * with GCC using the following command:
+ *
+ * .. code-block:: bash
+ *
+ *    $ gcc -std=c99 open62541.c myServer.c -o myServer
+ *
+ * Now start the server (and stop with ctrl-c):
+ *
+ * .. code-block:: bash
+ *
+ *    $ ./myServer
+ *
+ * You have now compiled and run your first OPC UA server. You can go ahead and
+ * browse the information model with a generic client, such as UAExpert. The
+ * server will be listening on ``opc.tcp://localhost:4840`` - go ahead and give
+ * it a try.
+ *
+ * In the following tutorials, you will be shown how to populate the server's
+ * information model and how to create a client application. */

+ 1 - 1
tools/c2rst.py

@@ -57,7 +57,7 @@ def last_line(c):
     for i in range(last-1,1,-1):
         if len(c[i].strip()) > 0:
             return i
-    return 1
+    return len(c)-1
 
 if len(sys.argv) < 2:
     print("Usage: python c2rst.py input.c/h output.rst")