mirror of
https://github.com/open62541/open62541.git
synced 2025-06-03 04:00:21 +00:00
doc(pubsub): Add documentation for PubSub
- Tutorial subscribe example - Pubsub realtime examples - Pubsub nodeset realtime examples Change-Id: I75b2581f87ccd0179d817c124b3e85c9de9b4d3a
This commit is contained in:
parent
b219820258
commit
563b150def
@ -60,7 +60,11 @@ generate_rst(${PROJECT_SOURCE_DIR}/examples/tutorial_server_object.c ${DOC_SRC_D
|
||||
generate_rst(${PROJECT_SOURCE_DIR}/examples/tutorial_server_method.c ${DOC_SRC_DIR}/tutorial_server_method.rst)
|
||||
generate_rst(${PROJECT_SOURCE_DIR}/examples/tutorial_client_firststeps.c ${DOC_SRC_DIR}/tutorial_client_firststeps.rst)
|
||||
generate_rst(${PROJECT_SOURCE_DIR}/examples/pubsub/tutorial_pubsub_publish.c ${DOC_SRC_DIR}/tutorial_pubsub_publish.rst)
|
||||
|
||||
generate_rst(${PROJECT_SOURCE_DIR}/examples/pubsub/tutorial_pubsub_subscribe.c ${DOC_SRC_DIR}/tutorial_pubsub_subscribe.rst)
|
||||
generate_rst(${PROJECT_SOURCE_DIR}/examples/pubsub_realtime/pubsub_TSN_publisher.c ${DOC_SRC_DIR}/pubsub_TSN_publisher.rst)
|
||||
generate_rst(${PROJECT_SOURCE_DIR}/examples/pubsub_realtime/pubsub_TSN_loopback.c ${DOC_SRC_DIR}/pubsub_TSN_loopback.rst)
|
||||
generate_rst(${PROJECT_SOURCE_DIR}/examples/pubsub_realtime/nodeset/pubsub_nodeset_rt_publisher.c ${DOC_SRC_DIR}/pubsub_nodeset_rt_publisher.rst)
|
||||
generate_rst(${PROJECT_SOURCE_DIR}/examples/pubsub_realtime/nodeset/pubsub_nodeset_rt_subscriber.c ${DOC_SRC_DIR}/pubsub_nodeset_rt_subscriber.rst)
|
||||
|
||||
# Doc targets
|
||||
|
||||
|
@ -17,3 +17,8 @@ Tutorials
|
||||
tutorial_server_alarms_conditions.rst
|
||||
tutorial_client_firststeps.rst
|
||||
tutorial_pubsub_publish.rst
|
||||
tutorial_pubsub_subscribe.rst
|
||||
pubsub_TSN_publisher.rst
|
||||
pubsub_TSN_loopback.rst
|
||||
pubsub_nodeset_rt_publisher.rst
|
||||
pubsub_nodeset_rt_subscriber.rst
|
||||
|
@ -5,11 +5,30 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* IMPORTANT ANNOUNCEMENT
|
||||
* The PubSub Subscriber API is currently not finished. This example can be used
|
||||
* to receive and display values that are published by tutorial_pubsub_publish
|
||||
* example in the TargetVariables of Subscriber Information Model .
|
||||
* .. _pubsub-tutorial:
|
||||
*
|
||||
* **IMPORTANT ANNOUNCEMENT**
|
||||
*
|
||||
* The PubSub Subscriber API is currently not finished. This Tutorial will be
|
||||
* continuously extended during the next PubSub batches. More details about the
|
||||
* PubSub extension and corresponding open62541 API are located here: :ref:`pubsub`.
|
||||
*
|
||||
* Subscribing Fields
|
||||
* ^^^^^^^^^^^^^^^^^^
|
||||
* The PubSub subscribe example demonstrates the simplest way to receive information over two transport layers such as
|
||||
* UDP and Ethernet, that are published by tutorial_pubsub_publish example and update values in the TargetVariables
|
||||
* of Subscriber Information Model.
|
||||
*
|
||||
* Run step of the application is as mentioned below:
|
||||
*
|
||||
* ./bin/examples/tutorial_pubsub_subscribe
|
||||
*
|
||||
* **Connection handling**
|
||||
*
|
||||
* PubSubConnections can be created and deleted on runtime. More details about
|
||||
* the system preconfiguration and connection can be found in ``tutorial_pubsub_connection.c``.
|
||||
*/
|
||||
|
||||
#include <open62541/plugin/log_stdout.h>
|
||||
#include <open62541/plugin/pubsub_udp.h>
|
||||
#include <open62541/server.h>
|
||||
@ -18,7 +37,7 @@
|
||||
|
||||
#include "ua_pubsub.h"
|
||||
|
||||
#ifdef UA_ENABLE_PUBSUB_ETH_UADP
|
||||
#if defined (UA_ENABLE_PUBSUB_ETH_UADP)
|
||||
#include <open62541/plugin/pubsub_ethernet.h>
|
||||
#endif
|
||||
|
||||
@ -61,6 +80,12 @@ addPubSubConnection(UA_Server *server, UA_String *transportProfile,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* **ReaderGroup**
|
||||
*
|
||||
* ReaderGroup is used to group a list of DataSetReaders. All ReaderGroups are
|
||||
* created within a PubSubConnection and automatically deleted if the connection
|
||||
* is removed. All network message related filters are only available in the DataSetReader. */
|
||||
/* Add ReaderGroup to the created connection */
|
||||
static UA_StatusCode
|
||||
addReaderGroup(UA_Server *server) {
|
||||
@ -78,6 +103,14 @@ addReaderGroup(UA_Server *server) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* **DataSetReader**
|
||||
*
|
||||
* DataSetReader can receive NetworkMessages with the DataSetMessage
|
||||
* of interest sent by the Publisher. DataSetReader provides
|
||||
* the configuration necessary to receive and process DataSetMessages
|
||||
* on the Subscriber side. DataSetReader must be linked with a
|
||||
* SubscribedDataSet and be contained within a ReaderGroup. */
|
||||
/* Add DataSetReader to the ReaderGroup */
|
||||
static UA_StatusCode
|
||||
addDataSetReader(UA_Server *server) {
|
||||
@ -107,7 +140,10 @@ addDataSetReader(UA_Server *server) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Set SubscribedDataSet type to TargetVariables data type
|
||||
/**
|
||||
* **SubscribedDataSet**
|
||||
*
|
||||
* Set SubscribedDataSet type to TargetVariables data type.
|
||||
* Add subscribedvariables to the DataSetReader */
|
||||
static UA_StatusCode
|
||||
addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) {
|
||||
@ -136,6 +172,12 @@ addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) {
|
||||
folderBrowseName, UA_NODEID_NUMERIC (0,
|
||||
UA_NS0ID_BASEOBJECTTYPE), oAttr, NULL, &folderId);
|
||||
|
||||
/**
|
||||
* **TargetVariables**
|
||||
*
|
||||
* The SubscribedDataSet option TargetVariables defines a list of Variable mappings between
|
||||
* received DataSet fields and target Variables in the Subscriber AddressSpace.
|
||||
* The values subscribed from the Publisher are updated in the value field of these variables */
|
||||
/* Create the TargetVariables with respect to DataSetMetaData fields */
|
||||
UA_FieldTargetVariable *targetVars = (UA_FieldTargetVariable *)
|
||||
UA_calloc(readerConfig.dataSetMetaData.fieldsSize, sizeof(UA_FieldTargetVariable));
|
||||
@ -172,6 +214,13 @@ addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* **DataSetMetaData**
|
||||
*
|
||||
* The DataSetMetaData describes the content of a DataSet. It provides the information necessary to decode
|
||||
* DataSetMessages on the Subscriber side. DataSetMessages received from the Publisher are decoded into
|
||||
* DataSet and each field is updated in the Subscriber based on datatype match of TargetVariable fields of Subscriber
|
||||
* and PublishedDataSetFields of Publisher */
|
||||
/* Define MetaData for TargetVariables */
|
||||
static void fillTestDataSetMetaData(UA_DataSetMetaDataType *pMetaData) {
|
||||
if(pMetaData == NULL) {
|
||||
@ -221,6 +270,8 @@ static void fillTestDataSetMetaData(UA_DataSetMetaDataType *pMetaData) {
|
||||
pMetaData->fields[3].valueRank = -1; /* scalar */
|
||||
}
|
||||
|
||||
/**
|
||||
* Followed by the main server code, making use of the above definitions */
|
||||
UA_Boolean running = true;
|
||||
static void stopHandler(int sign) {
|
||||
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
|
||||
@ -250,7 +301,7 @@ run(UA_String *transportProfile, UA_NetworkAddressUrlDataType *networkAddressUrl
|
||||
|
||||
config->pubsubTransportLayers[0] = UA_PubSubTransportLayerUDPMP();
|
||||
config->pubsubTransportLayersSize++;
|
||||
#ifdef UA_ENABLE_PUBSUB_ETH_UADP
|
||||
#if defined (UA_ENABLE_PUBSUB_ETH_UADP)
|
||||
config->pubsubTransportLayers[1] = UA_PubSubTransportLayerEthernet();
|
||||
config->pubsubTransportLayersSize++;
|
||||
#endif
|
||||
|
@ -2,14 +2,23 @@
|
||||
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
|
||||
|
||||
/**
|
||||
* .. _pubsub-tutorial:
|
||||
*
|
||||
* Publisher Realtime example using custom nodes
|
||||
* ---------------------------------------------
|
||||
*
|
||||
* The purpose of this example file is to use the custom nodes of the XML
|
||||
* file(pubDataModel.xml) for publisher
|
||||
* file(pubDataModel.xml) for publisher.
|
||||
* This Publisher example uses the two custom nodes (PublisherCounterVariable and Pressure)
|
||||
* created using the XML file(pubDataModel.xml) for publishing the packet
|
||||
* created using the XML file(pubDataModel.xml) for publishing the packet.
|
||||
* The pubDataModel.csv will contain the nodeids of custom nodes(object and variables) and
|
||||
* the nodeids of the custom nodes are harcoded inside the addDataSetField API
|
||||
* the nodeids of the custom nodes are harcoded inside the addDataSetField API.
|
||||
* This example uses two threads namely the Publisher and UserApplication. The Publisher thread is used to publish data at every cycle.
|
||||
* The UserApplication thread serves the functionality of the Control loop, which increments the counterdata to be published
|
||||
* by the Publisher and also writes the published data in a csv along with transmission timestamp.
|
||||
*
|
||||
* Run steps of the Publisher application as mentioned below:
|
||||
*
|
||||
* ./bin/examples/pubsub_nodeset_rt_publisher -i <iface>
|
||||
* For more information run ./bin/examples/pubsub_nodeset_rt_publisher -h */
|
||||
|
||||
@ -147,7 +156,6 @@ static void stopHandler(int sign) {
|
||||
* Nanosecond field in timespec is checked for overflowing and one second
|
||||
* is added to seconds field and nanosecond field is set to zero
|
||||
*/
|
||||
|
||||
static void nanoSecondFieldConversion(struct timespec *timeSpecValue) {
|
||||
/* Check if ns field is greater than '1 ns less than 1sec' */
|
||||
while (timeSpecValue->tv_nsec > (SECONDS -1)) {
|
||||
@ -158,6 +166,11 @@ static void nanoSecondFieldConversion(struct timespec *timeSpecValue) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* **Custom callback handling**
|
||||
*
|
||||
* Custom callback thread handling overwrites the default timer based
|
||||
* callback function with the custom (user-specified) callback interval. */
|
||||
/* Add a callback for cyclic repetition */
|
||||
static UA_StatusCode
|
||||
addPubSubApplicationCallback(UA_Server *server, UA_NodeId identifier,
|
||||
@ -195,7 +208,10 @@ removePubSubApplicationCallback(UA_Server *server, UA_NodeId identifier, UA_UInt
|
||||
"Pthread Join Failed thread: %ld\n", callbackId);
|
||||
}
|
||||
|
||||
/* If the external data source is written over the information model, the
|
||||
/**
|
||||
* **External data source handling**
|
||||
*
|
||||
* If the external data source is written over the information model, the
|
||||
* externalDataWriteCallback will be triggered. The user has to take care and assure
|
||||
* that the write leads not to synchronization issues and race conditions. */
|
||||
static UA_StatusCode
|
||||
@ -392,12 +408,14 @@ updateMeasurementsPublisher(struct timespec start_time,
|
||||
measurementsPublisher++;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* **Publisher thread routine**
|
||||
*
|
||||
* The Publisher thread sleeps for 60% of the cycletime (250us) and prepares the tranmission packet within 40% of
|
||||
* cycletime. The data published by this thread in one cycle is subscribed by the subscriber thread of pubsub_nodeset_rt_subscriber in the
|
||||
* next cycle (two cycle timing model).
|
||||
*
|
||||
* The publisherETF function is the routine used by the publisher thread.
|
||||
* This routine publishes the data at a cycle time of 250us.
|
||||
*/
|
||||
void *publisherETF(void *arg) {
|
||||
struct timespec nextnanosleeptime;
|
||||
@ -453,6 +471,8 @@ void *publisherETF(void *arg) {
|
||||
/**
|
||||
* **UserApplication thread routine**
|
||||
*
|
||||
* The userapplication thread will wakeup at 30% of cycle time and handles the userdata in the Information Model.
|
||||
* This thread is used to increment the counterdata that will be published by the Publisher thread and also writes the published data in a csv.
|
||||
*/
|
||||
void *userApplicationPub(void *arg) {
|
||||
struct timespec nextnanosleeptimeUserApplication;
|
||||
@ -477,6 +497,12 @@ void *userApplicationPub(void *arg) {
|
||||
return (void*)NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* **Thread creation**
|
||||
*
|
||||
* The threadcreation functionality creates thread with given threadpriority, coreaffinity. The function returns the threadID of the newly
|
||||
* created thread.
|
||||
*/
|
||||
static pthread_t threadCreation(UA_Int32 threadPriority, UA_Int32 coreAffinity, void *(*thread) (void *), char *applicationName, void *serverConfig){
|
||||
|
||||
/* Core affinity set */
|
||||
@ -517,6 +543,13 @@ static pthread_t threadCreation(UA_Int32 threadPriority, UA_Int32 coreAffinity,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* **Usage function**
|
||||
*
|
||||
* The usage function gives the list of options that can be configured in the application.
|
||||
*
|
||||
* ./bin/examples/pubsub_nodeset_rt_publisher -h gives the list of options for running the application.
|
||||
*/
|
||||
static void usage(char *appname)
|
||||
{
|
||||
fprintf(stderr,
|
||||
@ -540,9 +573,9 @@ static void usage(char *appname)
|
||||
}
|
||||
|
||||
/**
|
||||
* ***Main Server code**
|
||||
* **Main Server code**
|
||||
*
|
||||
* The main function contains publisher threads running
|
||||
* The main function contains publisher threads running
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
signal(SIGINT, stopHandler);
|
||||
|
@ -1,13 +1,22 @@
|
||||
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
|
||||
* See http://creativecommons.org/publicdomain/zero/1.0/ for more information. */
|
||||
/**
|
||||
* .. _pubsub-tutorial:
|
||||
*
|
||||
* Subscriber Realtime example using custom nodes
|
||||
* ---------------------------------------------
|
||||
*
|
||||
* The purpose of this example file is to use the custom nodes of the XML
|
||||
* file(subDataModel.xml) for subscriber
|
||||
* file(subDataModel.xml) for subscriber.
|
||||
* This Subscriber example uses the two custom nodes (SubscriberCounterVariable and Pressure)
|
||||
* created using the XML file(subDataModel.xml) for subscribing the packet
|
||||
* created using the XML file(subDataModel.xml) for subscribing the packet.
|
||||
* The subDataModel.csv will contain the nodeids of custom nodes(object and variables) and
|
||||
* the nodeids of the custom nodes are harcoded inside the addSubscribedVariables API
|
||||
*
|
||||
* This example uses two threads namely the Subscriber and UserApplication. The Subscriber thread is used to subscribe to data at every cycle.
|
||||
* The UserApplication thread serves the functionality of the Control loop, which reads the Information Model of the Subscriber and
|
||||
* the new counterdata will be written in the csv along with received timestamp.
|
||||
*
|
||||
* Run steps of the Subscriber application as mentioned below:
|
||||
* ./bin/examples/pubsub_nodeset_rt_subscriber -i <iface>
|
||||
* For more information run ./bin/examples/pubsub_nodeset_rt_subscriber -h */
|
||||
@ -72,9 +81,7 @@ static UA_Int32 userAppCore = DEFAULT_USER_APP_CORE;
|
||||
/* user data write in Information model */
|
||||
/* After 60% is left for publisher */
|
||||
static UA_Double userAppWakeupPercentage = 0.3;
|
||||
/* Publisher will sleep for 60% of cycle time and then prepares the */
|
||||
/* transmission packet within 40% */
|
||||
/* after some prototyping and analyzing it */
|
||||
/* Subscriber will wake up at the start of cycle time and then receives the packet */
|
||||
static UA_Double subWakeupPercentage = 0;
|
||||
static UA_Boolean fileWrite = UA_FALSE;
|
||||
|
||||
@ -139,7 +146,6 @@ static void stopHandler(int sign) {
|
||||
* Nanosecond field in timespec is checked for overflowing and one second
|
||||
* is added to seconds field and nanosecond field is set to zero
|
||||
*/
|
||||
|
||||
static void nanoSecondFieldConversion(struct timespec *timeSpecValue) {
|
||||
/* Check if ns field is greater than '1 ns less than 1sec' */
|
||||
while (timeSpecValue->tv_nsec > (SECONDS -1)) {
|
||||
@ -150,6 +156,11 @@ static void nanoSecondFieldConversion(struct timespec *timeSpecValue) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* **Custom callback handling**
|
||||
*
|
||||
* Custom callback thread handling overwrites the default timer based
|
||||
* callback function with the custom (user-specified) callback interval. */
|
||||
/* Add a callback for cyclic repetition */
|
||||
static UA_StatusCode
|
||||
addPubSubApplicationCallback(UA_Server *server, UA_NodeId identifier, UA_ServerCallback callback,
|
||||
@ -186,7 +197,10 @@ removePubSubApplicationCallback(UA_Server *server, UA_NodeId identifier, UA_UInt
|
||||
"Pthread Join Failed thread: %ld\n", callbackId);
|
||||
}
|
||||
|
||||
/* If the external data source is written over the information model, the
|
||||
/**
|
||||
* **External data source handling**
|
||||
*
|
||||
* If the external data source is written over the information model, the
|
||||
* externalDataWriteCallback will be triggered. The user has to take care and assure
|
||||
* that the write leads not to synchronization issues and race conditions. */
|
||||
static UA_StatusCode
|
||||
@ -206,6 +220,12 @@ externalDataReadNotificationCallback(UA_Server *server, const UA_NodeId *session
|
||||
//allow read without any preparation
|
||||
return UA_STATUSCODE_GOOD;
|
||||
}
|
||||
|
||||
/**
|
||||
* **Subscriber Connection Creation**
|
||||
*
|
||||
* Create Subscriber connection for the Subscriber thread
|
||||
*/
|
||||
static void
|
||||
addPubSubConnectionSubscriber(UA_Server *server, UA_NetworkAddressUrlDataType *networkAddressUrlSubscriber){
|
||||
UA_StatusCode retval = UA_STATUSCODE_GOOD;
|
||||
@ -224,6 +244,12 @@ addPubSubConnectionSubscriber(UA_Server *server, UA_NetworkAddressUrlDataType *n
|
||||
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,"The PubSub Connection was created successfully!");
|
||||
}
|
||||
|
||||
/**
|
||||
* **ReaderGroup**
|
||||
*
|
||||
* ReaderGroup is used to group a list of DataSetReaders. All ReaderGroups are
|
||||
* created within a PubSubConnection and automatically deleted if the connection
|
||||
* is removed. */
|
||||
/* Add ReaderGroup to the created connection */
|
||||
static void
|
||||
addReaderGroup(UA_Server *server) {
|
||||
@ -242,7 +268,10 @@ addReaderGroup(UA_Server *server) {
|
||||
&readerGroupIdentifier);
|
||||
}
|
||||
|
||||
/* Set SubscribedDataSet type to TargetVariables data type
|
||||
/**
|
||||
* **SubscribedDataSet**
|
||||
*
|
||||
* Set SubscribedDataSet type to TargetVariables data type
|
||||
* Add SubscriberCounter variable to the DataSetReader */
|
||||
static void addSubscribedVariables (UA_Server *server) {
|
||||
if (server == NULL) {
|
||||
@ -294,6 +323,14 @@ static void addSubscribedVariables (UA_Server *server) {
|
||||
readerConfig.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* **DataSetReader**
|
||||
*
|
||||
* DataSetReader can receive NetworkMessages with the DataSetMessage
|
||||
* of interest sent by the Publisher. DataSetReader provides
|
||||
* the configuration necessary to receive and process DataSetMessages
|
||||
* on the Subscriber side. DataSetReader must be linked with a
|
||||
* SubscribedDataSet and be contained within a ReaderGroup. */
|
||||
/* Add DataSetReader to the ReaderGroup */
|
||||
static void
|
||||
addDataSetReader(UA_Server *server) {
|
||||
@ -356,7 +393,8 @@ addDataSetReader(UA_Server *server) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribed data handling**
|
||||
* **Subscribed data handling**
|
||||
*
|
||||
* The subscribed data is updated in the array using this function Subscribed data handling**
|
||||
*/
|
||||
static void
|
||||
@ -370,9 +408,9 @@ updateMeasurementsSubscriber(struct timespec receive_time, UA_UInt64 counterValu
|
||||
/**
|
||||
* **Subscriber thread routine**
|
||||
*
|
||||
* Subscriber thread will wakeup during the start of cycle at 250us interval and check if the packets are received.
|
||||
* The subscriber function is the routine used by the subscriber thread.
|
||||
*/
|
||||
|
||||
void *subscriber(void *arg) {
|
||||
UA_Server* server;
|
||||
UA_ReaderGroup* currentReaderGroup;
|
||||
@ -406,6 +444,8 @@ void *subscriber(void *arg) {
|
||||
/**
|
||||
* **UserApplication thread routine**
|
||||
*
|
||||
* The userapplication thread will wakeup at 30% of cycle time and handles the userdata in the Information Model.
|
||||
* This thread is used to write the counterdata that is subscribed by the Subscriber thread in a csv.
|
||||
*/
|
||||
void *userApplicationSub(void *arg) {
|
||||
struct timespec nextnanosleeptimeUserApplication;
|
||||
@ -430,6 +470,12 @@ void *userApplicationSub(void *arg) {
|
||||
return (void*)NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* **Thread creation**
|
||||
*
|
||||
* The threadcreation functionality creates thread with given threadpriority, coreaffinity. The function returns the threadID of the newly
|
||||
* created thread.
|
||||
*/
|
||||
static pthread_t threadCreation(UA_Int32 threadPriority, UA_Int32 coreAffinity, void *(*thread) (void *), \
|
||||
char *applicationName, void *serverConfig){
|
||||
|
||||
@ -471,6 +517,13 @@ static pthread_t threadCreation(UA_Int32 threadPriority, UA_Int32 coreAffinity,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* **Usage function**
|
||||
*
|
||||
* The usage function gives the list of options that can be configured in the application.
|
||||
*
|
||||
* ./bin/examples/pubsub_nodeset_rt_subscriber -h gives the list of options for running the application.
|
||||
*/
|
||||
static void usage(char *appname)
|
||||
{
|
||||
fprintf(stderr,
|
||||
@ -492,7 +545,7 @@ static void usage(char *appname)
|
||||
}
|
||||
|
||||
/**
|
||||
* ***Main Server code**
|
||||
* **Main Server code**
|
||||
*
|
||||
* The main function contains subscriber threads running
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user