From 5c70c3a4f3ffe1d4f4691467d13ff30dbfa2f891 Mon Sep 17 00:00:00 2001 From: julianbermudez Date: Mon, 3 Sep 2018 14:52:16 +0200 Subject: [PATCH 01/16] Modified Subscriber example. --- docs/quickstart.rst | 182 ++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 84 deletions(-) diff --git a/docs/quickstart.rst b/docs/quickstart.rst index a6a80dd5..418b180f 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -124,97 +124,111 @@ The code of the *SubscriberHelloWorldClient* is the following: .. code-block:: C - #include "HelloWorldWriter.h" - - #include - #include - #include //strcmp - #include //atoi - - #define STREAM_HISTORY 8 - #define BUFFER_SIZE MR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY - - int main(int args, char** argv) - { - if(args >= 2 && (0 == strcmp("-h", argv[1]) || 0 == strcmp("--help", argv[1]) || 0 == atoi(argv[1]))) + #include "HelloWorld.h" + + #include + #include //strcmp + #include //atoi + #include + + #define STREAM_HISTORY 8 + #define BUFFER_SIZE MR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY + + void on_topic(mrSession* session, mrObjectId object_id, uint16_t request_id, mrStreamId stream_id, struct MicroBuffer* mb, void* args) { - printf("usage: program [-h | --help | ]\n"); - return 0; + (void) session; (void) object_id; (void) request_id; (void) stream_id; + + HelloWorld topic; + HelloWorld_deserialize_topic(mb, &topic); + + printf("Received topic: %s, id: %i\n", topic.message, topic.index); + + uint32_t* count_ptr = (uint32_t*) args; + (*count_ptr)++; } - - uint32_t max_topics = (args == 2) ? (uint32_t)atoi(argv[1]) : UINT32_MAX; - - // Transport - mrUDPTransport transport; - if(!mr_init_udp_transport(&transport, "127.0.0.1", 2018)) + + int main(int args, char** argv) { - printf("Error at create transport.\n"); - return 1; - } - - // Session - mrSession session; - mr_init_session(&session, &transport.comm, 0xAAAABBBB); - if(!mr_create_session(&session)) - { - printf("Error at create session.\n"); - return 1; - } - - // Streams - uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; - mrStreamId reliable_out = mr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); - - uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; - mr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); - - // Create entities - mrObjectId participant_id = mr_object_id(0x01, MR_PARTICIPANT_ID); - const char* participant_ref = "default participant"; - uint16_t participant_req = mr_write_create_participant_ref(&session, reliable_out, participant_id, participant_ref, MR_REPLACE); - - mrObjectId topic_id = mr_object_id(0x01, MR_TOPIC_ID); - const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = mr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, MR_REPLACE); - - mrObjectId publisher_id = mr_object_id(0x01, MR_PUBLISHER_ID); - const char* publisher_xml = ""; - uint16_t publisher_req = mr_write_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, MR_REPLACE); - - mrObjectId datawriter_id = mr_object_id(0x01, MR_DATAWRITER_ID); - const char* datawriter_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datawriter_req = mr_write_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, MR_REPLACE); - - // Send create entities message and wait its status - uint8_t status[4]; - uint16_t requests[4] = {participant_req, topic_req, publisher_req, datawriter_req}; - if(!mr_run_session_until_status(&session, 1000, requests, status, 4)) - { - printf("Error at create entities: participant: %i topic: %i publisher: %i darawriter: %i\n", status[0], status[1], status[2], status[3]); - return 1; - } - - // Write topics - bool connected = true; - uint32_t count = 0; - while(connected && count < max_topics) - { - HelloWorld topic = {count++, "Hello DDS world!"}; - (void) mr_write_HelloWorld_topic(&session, reliable_out, datawriter_id, &topic); - - connected = mr_run_session_until_timeout(&session, 1000); - if(connected) + if(args >= 2 && (0 == strcmp("-h", argv[1]) || 0 == strcmp("--help", argv[1]) || 0 == atoi(argv[1]))) { - printf("Sent topic: %s, id: %i\n", topic.message, topic.index); + printf("usage: program [-h | --help | ]\n"); + return 0; + } + + uint32_t count = 0; + uint32_t max_topics = (args == 2) ? (uint32_t)atoi(argv[1]) : UINT32_MAX; + + // Transport + mrUDPTransport transport; + if(!mr_init_udp_transport(&transport, "127.0.0.1", 2018)) + { + printf("Error at create transport.\n"); + return 1; + } + + // Session + mrSession session; + mr_init_session(&session, &transport.comm, 0xCCCCDDDD); + mr_set_topic_callback(&session, on_topic, &count); + if(!mr_create_session(&session)) + { + printf("Error at create session.\n"); + return 1; } + + // Streams + uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; + mrStreamId reliable_out = mr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + + uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; + mrStreamId reliable_in = mr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + + // Create entities + mrObjectId participant_id = mr_object_id(0x01, MR_PARTICIPANT_ID); + const char* participant_ref = "default participant"; + uint16_t participant_req = mr_write_create_participant_ref(&session, reliable_out, participant_id, 0, participant_ref, MR_REPLACE); + + mrObjectId topic_id = mr_object_id(0x01, MR_TOPIC_ID); + const char* topic_xml = "HelloWorldTopicHelloWorld"; + uint16_t topic_req = mr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, MR_REPLACE); + + mrObjectId subscriber_id = mr_object_id(0x01, MR_SUBSCRIBER_ID); + const char* subscriber_xml = ""; + uint16_t subscriber_req = mr_write_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, MR_REPLACE); + + mrObjectId datareader_id = mr_object_id(0x01, MR_DATAREADER_ID); + const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; + uint16_t datareader_req = mr_write_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, MR_REPLACE); + + // Send create entities message and wait its status + uint8_t status[4]; + uint16_t requests[4] = {participant_req, topic_req, subscriber_req, datareader_req}; + if(!mr_run_session_until_status(&session, 1000, requests, status, 4)) + { + printf("Error at create entities: participant: %i topic: %i subscriber: %i datareader: %i\n", status[0], status[1], status[2], status[3]); + return 1; + } + + // Request topics + mrDeliveryControl delivery_control = {0}; + delivery_control.max_samples = MR_MAX_SAMPLES_UNLIMITED; + uint16_t read_data_req = mr_write_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); + + // Read topics + bool connected = true; + while(connected && count < max_topics) + { + uint8_t read_data_status; + connected = mr_run_session_until_status(&session, MR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); + } + + // Delete resources + mr_delete_session(&session); + mr_close_udp_transport(&transport); + + return 0; } - // Delete resources - mr_delete_session(&session); - mr_close_udp_transport(&transport); - - return 0; - } At this moment, the subscriber will receive the topics that are sending by the publisher. From 2d4b816730862aec729434d96df40379a9d39d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Mon, 17 Sep 2018 14:41:34 +0200 Subject: [PATCH 02/16] Minor change at client/create_session docs (#1) * Added relevant line into create_session explanation * Updated comment. --- docs/client.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index c0611662..67c1318e 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -129,8 +129,9 @@ Once this function is called, a ``create_session`` call can be performed. :session: Session structure where manage the session data. :key: The identifying key of the client. All clients connected to an agent must have different key. -:comm: Connection used for connecting to the agent. - All different transports have an attribute mrCommunication. +:comm: Communication used for connecting to the agent. + All different transports have a common attribute mrCommunication. + This parameter can not be shared between active sessions. ------ From 0bc4c1f9f0908dc65496fbea810bac76250f3a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Wed, 19 Sep 2018 16:03:15 +0200 Subject: [PATCH 03/16] Doc changes for accept branch: run session api change (#2) * Added documentation for 'run session api change' pull request. * Updated run_session doc * Corrected run_session description. --- docs/client.rst | 65 ++++++++++++++++++++++++++++++++----------- docs/introduction.rst | 2 +- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index 67c1318e..45386950 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -247,7 +247,17 @@ The number of available calls to this function must be less or equal than ``CONF .. code-block:: c - void mr_run_session_until_timeout(mrSession* session, int timeout); + void mr_flash_output_streams(mrSession* session); + +Flashes all output streams sending the data through the transport. + +:session: Session structure previously initialized. + +------ + +.. code-block:: c + + void mr_run_session_time(mrSession* session, int time); The main library function. This function processes the internal functionality of a session. @@ -255,15 +265,38 @@ This implies: 1. Flashes all output streams sending the data through the transport. 2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. -3. Listens messages from the agent and call the associated callback (a topic callback or a status callback). +3. Listens messages from the agent and call the associated callback if exists (a topic callback or a status callback). -The ``_until_timeout`` suffix function version will perform these actions until the waiting for a new message reaches the timeout. -Only if the time waiting for a message overcome the timeout, the function finished. +The ``time`` suffix function version will perform these actions and will listen messages for a ``time`` duration. +Only when the time waiting for a message overcome the ``time`` duration, the function finishes. The function will return ``true`` if the sent data have been confirmed, ``false`` otherwise. :session: Session structure previously initialized. -:timeout: Time to waiting a new message, in milliseconds. - For waiting without timeout, set the value to MR_TIMEOUT_INF +:time: Time for waiting, in milliseconds. + For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` + +------ + +.. code-block:: c + + void mr_run_session_until_timeout(mrSession* session, int timeout); + +The main library function. +This function processes the internal functionality of a session. +This implies: + +1. Flashes all output streams sending the data through the transport. +2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. +3. Listens messages from the agent and call the associated callback if exists (a topic callback or a status callback). + +The ``_until_timeout`` suffix function version will perform these actions until receiving one message. +Once the message has been received or the timeout has been reached, the function finishes. +Only when the time waiting for a message overcome the ``timeout`` duration, the function finishes. +The function will return ``true`` if has received a message, ``false`` if the timeout has been reached. + +:session: Session structure previously initialized. +:timeout: Time for waiting a new message, in milliseconds. + For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` ------ @@ -277,15 +310,15 @@ This implies: 1. Flashes all output streams sending the data through the transport. 2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. -3. Listenes messages from the agent and call the associated callback (a topic callback or a status callback). +3. Listenes messages from the agent and call the associated callback if exists (a topic callback or a status callback). -The ``_until_confirm_delivery`` suffix function version will perform these actions -until the waiting for a new message reaches the timeout or until the output reliable streams confirm that the sent messages have been received by the agent. +The ``_until_confirm_delivery`` suffix function version will perform these actions during ``timeout`` duration +or until the output reliable streams confirm that the sent messages have been received by the agent. The function will return ``true`` if the sent data have been confirmed, ``false`` otherwise. :session: Session structure previously initialized. -:timeout: Maximun time to wait for a new message, in milliseconds. - For waiting without timeout, set the value to MR_TIMEOUT_INF +:timeout: Maximun time for waiting to a new message, in milliseconds. + For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` ------ @@ -299,15 +332,15 @@ This implies: 1. Flashes all output streams sending the data through the transport. 2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. -3. Listenes messages from the agent and call the associated callback (a topic callback or a status callback). +3. Listenes messages from the agent and call the associated callback if exists (a topic callback or a status callback). -The ``_until_status`` suffix function version will perform these actions -until the waiting for a new message reaches the timeout or until the requested status had been received. +The ``_until_status`` suffix function version will perform these actions during ``timeout`` duration +or until the requested status had been received. The function will return ``true`` if all status have been received and all of them have the value ``MR_STATUS_OK`` or ``MR_STATUS_OK_MATCHED``, ``false`` otherwise. :session: Session structure previously initialized. -:timeout: Maximun time to wait for a new message, in milliseconds. - For waiting without timeout, set the value to MR_TIMEOUT_INF +:timeout: Maximun time for waiting to a new message, in milliseconds. + For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` :request_list: An array of request to confirm with a status. :status_list: An uninitialized array with the same size as ``request_list`` where the status values will be written. The position of a status in the list corresponds to the request at the same position in ``request_list``. diff --git a/docs/introduction.rst b/docs/introduction.rst index 801c3fdd..4c6a0aeb 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -33,7 +33,7 @@ RTPS is also the wire interoperability protocol defined for the `DDS` standard, For deeper information please refer to the official documentation: `eProsima Fast RTPS `_ Operations and entities ----------- +----------------------- *Micro RTPS* communication between XRCE Client and XRCE Agent is based upon :ref:`operations_label` and responses. Clients request operations to the Agent. The Agent will process the received operations and generate responses with the result of these operations. From 500f1c3d9aaa5b1cd74799ea41fe730fcb164ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Mon, 24 Sep 2018 16:32:41 +0200 Subject: [PATCH 04/16] Updated docs for the new Write Access profile API (#3) * Refs #3402. Updated docs for new Write Access profile. * Changes to accept pull request #3 * Changes to accept pull request. --- docs/client.rst | 33 ++++++++++++++++++--------- docs/gen.rst | 7 +++--- docs/getting_started.rst | 22 ++++++++++-------- docs/operations.rst | 2 +- docs/quickstart.rst | 48 ++++++++++++++++++++++------------------ 5 files changed, 65 insertions(+), 47 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index 45386950..9abc92a2 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -48,6 +48,9 @@ For incorporating the changes to your project, is necessary to run the ``cmake`` ``PROFILE_READ_ACCESS=`` Enables or disables the functions related to read topics. +``PROFILE_WRITE_ACCESS=`` + Enables or disables the functions related to write topics. + ``PROFILE_UDP_TRANSPORT=`` Enables or disables the posibility to connect with the agent by UDP. @@ -350,7 +353,7 @@ The function will return ``true`` if all status have been received and all of th Create entities by XML profile `````````````````````````````` -These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` is enabled into ``client.config`` file. +These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` is enabled in the ``client.config`` file. The declaration of these function can be found in ``micrortps/client/profile/session/create_entities_xml.h``. ------ @@ -471,7 +474,7 @@ Create a `datareader` entity in the agent. Create entities by reference profile ```````````````````````````````````` -These functions are enabled when ``PROFILE_CREATE_ENTITIES_REF`` is enabled into ``client.config`` file. +These functions are enabled when ``PROFILE_CREATE_ENTITIES_REF`` is enabled in the ``client.config`` file. The declaration of these function can be found in ``micrortps/client/profile/session/create_entities_ref.h``. ------ @@ -497,7 +500,7 @@ Create a `datareader` entity in the agent. Create entities common profile `````````````````````````````` -These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` or ``PROFILE_CREATE_ENTITIES_REF`` are enabled into ``client.config`` file. +These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` or ``PROFILE_CREATE_ENTITIES_REF`` are enabled in the ``client.config`` file. The declaration of these function can be found in ``micrortps/client/profile/session/common_create_entities.h``. ------ @@ -516,7 +519,7 @@ Removes a entity. Read access profile ``````````````````` -These functions are enabled when PROFILE_READ_ACCESS is enabled into ``client.config`` file. +These functions are enabled when PROFILE_READ_ACCESS is enabled in the ``client.config`` file. The declaration of these function can be found in ``micrortps/client/profile/session/read_access.h``. ------ @@ -543,23 +546,30 @@ If there is an error, a status error will be sent by the agent. Write access profile ```````````````````` -These functions are generated automatically by `MicroRTPSGen` utility with the ``-write-access-profile`` option enabled over an idl file with a topic `TOPICTYPE`. -The declaration of these function can be found in the generated file ``TOPICTYPEWriter.h``. +These functions are enabled when PROFILE_WRITE_ACCESS is enabled in the ``client.config`` file. +The declaration of these function can be found in ``micrortps/client/profile/session/write_access.h``. ------ .. code-block:: c - bool mr_write_TOPICTYPE_topic(mrSession* session, mrStreamId stream_id, mrObjectId datawriter_id, const TOPICTYPE* topic); + bool mr_prepare_output_stream(mrSession* session, mrStreamId stream_id, mrObjectId datawriter_id, + struct MicroBuffer* mb_topic, uint32_t topic_size); -This function writes a topic into a stream. -If the returned value is ``true``, the topic has been serialized. +Requests a writing into a specific output stream. +For that this function will initialize a ``MicroBuffer`` struct where a topic of ``topic_size`` size must be serialized. +If the returned value is ``true``, exists the necessary gap for writing a ``topic_size`` bytes into the stream. +If the returned value is ``false``, the topic can no be serialized into the stream. The topic will be sent in the next ``run_session`` function. +NOTE: All `topic_size` bytes requested will be sent to the agent after a ``run_session`` call, no matter if the ``MicroBuffer`` has been used or not. + :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. -:object_id: The DataWriter ID that will write the topic to the DDS World. -:topic: The topic that will be sent to the agent. +:datawriter_id: The DataWriter ID that will write the topic to the DDS World. +:mb_topic: A ``MicroBuffer`` struct used to serialize the topic. + This struct points to a requested gap into the stream. +:topic_size: The bytes that will be reserved in the stream. ------ @@ -603,6 +613,7 @@ It counts the number of bytes that the topic will need in a `MicroBuffer`. :topic: Struct to count the size. :size: Number of bytes already written into the `MicroBuffer`. + Typically its value is `0` if the purpose is to use in ``mr_prepare_output_stream`` function. ------ diff --git a/docs/gen.rst b/docs/gen.rst index b3f38acb..b2f66106 100644 --- a/docs/gen.rst +++ b/docs/gen.rst @@ -63,15 +63,14 @@ it will generate the following header file and its corresponding source: #endif // _ShapeType_H_ -*Micro RTPS Gen* is also able to generate a writing function for the topic. It is enabled with the ``-write-access-profile`` option: :: - - $ micrortpsgen -write-access-profile *Micro RTPS Gen* is also able to generate both *publisher* and *subscriber* source code examples related with the topic speficified in the IDL file adding the flag ``-example``: :: $ micrortpsgen -example -With the ``-example`` flag, the ``-write_access-profile`` option is automatically enabled. + +In order to use these examples, the client library must be compiled with the ``WRITE_ACCESS_PROFILE`` option for the *publisher* +and the ``READ_ACCESS_PROFILE`` option for the *subscriber*. Installation ------------ diff --git a/docs/getting_started.rst b/docs/getting_started.rst index f90f0106..1a95e370 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -25,9 +25,7 @@ We will use HelloWorld as our Topic whose IDL is the following: :: In the *Client* we need to create an equivalent C type with its serialization/deserialization code. This is done automatically by :ref:`micrortpsgen_label`: :: - $ micrortpsgen -write-access-profile HelloWorld.idl - -Because we want to write this topic into the DDS world, we have added the ``-write-access-option`` that will creates another file with functionality for writing topics. + $ micrortpsgen HelloWorld.idl Initialize a Session ^^^^^^^^^^^^^^^^^^^^ @@ -209,14 +207,20 @@ For creating a message with data, first we must to decide which stream we want t .. code-block:: C HelloWorld topic = {count++, "Hello DDS world!"}; - (void) mr_write_HelloWorld_topic(&session, reliable_out, datawriter_id, &topic); + + MicroBuffer mb; + uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0); + (void) mr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); + (void) HelloWorld_serialize_topic(&mb, &topic); mr_run_session_until_confirmed_delivery(&session, 1000); -``mr_write_HelloWorld_topic`` function is automatically generated by :ref:`micrortpsgen_label` from the IDL. -This function serializes the topic into stream. -If the stream is available and the topic fix into it, a valid *request id* is returned. -``datawriter_id`` correspond to the data writer entity used for sending the data. +``HelloWorld_size_of_topic`` and ``HelloWorld_serialize_topic`` functions are automatically generated by :ref:`micrortpsgen_label` from the IDL. +The function ``mr_prepare_output_stream`` requests a writing for a topic of ``topic_size`` size into the reliable stream represented by ``reliable_out``, +with a ``datawriter_id`` (correspond to the data writer entity used for sending the data in the `DDS World`). +If the stream is available and the topic fits in it, the function will initialize the ``MicroBuffer`` structure ``mb``. +Once the ``MicroBuffer`` is prepared, the topic can be serialized into it. +We are careless about ``mr_prepare_output_stream`` return value because the serialization only will occur if the ``MicroBuffer` is valid`` After the write function, as happend with the creation of entities, the topic has been serialized into the buffer but it has not been sent yet. To send the topic is necessary call to a ``run_session`` function. @@ -256,7 +260,7 @@ To know which kind of Topic has been received, we can use the ``object_id`` para This id of the ``object_id`` corresponds to the DataReader that has read the Topic. The ``args`` argument correspond to user free data. -Closing my Client +Closing the Client ^^^^^^^^^^^^^^^^^ To close a *Client*, we must perform two steps. First, we need to tell the agent that the session is no longer available. diff --git a/docs/operations.rst b/docs/operations.rst index 38f2822d..f9e02732 100644 --- a/docs/operations.rst +++ b/docs/operations.rst @@ -27,7 +27,7 @@ Types Analogous to create entities a session can to drop the entities on the *Agent*. To drop an entity you need to request a deletion of the entity to the *Agent* using the entity ID. -`Read Data` +`Request Data` This operation configures how do you want to receive data, and the Agent will deliver it from the DDS to your *Client*. This data will be receive asynchronously, in accordance with the data delivery control setted in this operation. Reading data is done using a DataReader entity. diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 418b180f..220e0708 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -100,7 +100,11 @@ The code of the *PublishHelloWorldClient* is the following: while(connected && count < max_topics) { HelloWorld topic = {count++, "Hello DDS world!"}; - (void) mr_write_HelloWorld_topic(&session, reliable_out, datawriter_id, &topic); + + MicroBuffer mb; + uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0); + mr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); + HelloWorld_serialize_topic(&mb, &topic); connected = mr_run_session_until_timeout(&session, 1000); if(connected) @@ -125,28 +129,28 @@ The code of the *SubscriberHelloWorldClient* is the following: .. code-block:: C #include "HelloWorld.h" - + #include #include //strcmp #include //atoi #include - + #define STREAM_HISTORY 8 #define BUFFER_SIZE MR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY - + void on_topic(mrSession* session, mrObjectId object_id, uint16_t request_id, mrStreamId stream_id, struct MicroBuffer* mb, void* args) { (void) session; (void) object_id; (void) request_id; (void) stream_id; - + HelloWorld topic; HelloWorld_deserialize_topic(mb, &topic); - + printf("Received topic: %s, id: %i\n", topic.message, topic.index); - + uint32_t* count_ptr = (uint32_t*) args; (*count_ptr)++; } - + int main(int args, char** argv) { if(args >= 2 && (0 == strcmp("-h", argv[1]) || 0 == strcmp("--help", argv[1]) || 0 == atoi(argv[1]))) @@ -154,10 +158,10 @@ The code of the *SubscriberHelloWorldClient* is the following: printf("usage: program [-h | --help | ]\n"); return 0; } - + uint32_t count = 0; uint32_t max_topics = (args == 2) ? (uint32_t)atoi(argv[1]) : UINT32_MAX; - + // Transport mrUDPTransport transport; if(!mr_init_udp_transport(&transport, "127.0.0.1", 2018)) @@ -165,7 +169,7 @@ The code of the *SubscriberHelloWorldClient* is the following: printf("Error at create transport.\n"); return 1; } - + // Session mrSession session; mr_init_session(&session, &transport.comm, 0xCCCCDDDD); @@ -175,31 +179,31 @@ The code of the *SubscriberHelloWorldClient* is the following: printf("Error at create session.\n"); return 1; } - + // Streams uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; mrStreamId reliable_out = mr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); - + uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; mrStreamId reliable_in = mr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); - + // Create entities mrObjectId participant_id = mr_object_id(0x01, MR_PARTICIPANT_ID); const char* participant_ref = "default participant"; uint16_t participant_req = mr_write_create_participant_ref(&session, reliable_out, participant_id, 0, participant_ref, MR_REPLACE); - + mrObjectId topic_id = mr_object_id(0x01, MR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; uint16_t topic_req = mr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, MR_REPLACE); - + mrObjectId subscriber_id = mr_object_id(0x01, MR_SUBSCRIBER_ID); const char* subscriber_xml = ""; uint16_t subscriber_req = mr_write_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, MR_REPLACE); - + mrObjectId datareader_id = mr_object_id(0x01, MR_DATAREADER_ID); const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; uint16_t datareader_req = mr_write_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, MR_REPLACE); - + // Send create entities message and wait its status uint8_t status[4]; uint16_t requests[4] = {participant_req, topic_req, subscriber_req, datareader_req}; @@ -208,12 +212,12 @@ The code of the *SubscriberHelloWorldClient* is the following: printf("Error at create entities: participant: %i topic: %i subscriber: %i datareader: %i\n", status[0], status[1], status[2], status[3]); return 1; } - + // Request topics mrDeliveryControl delivery_control = {0}; delivery_control.max_samples = MR_MAX_SAMPLES_UNLIMITED; uint16_t read_data_req = mr_write_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); - + // Read topics bool connected = true; while(connected && count < max_topics) @@ -221,11 +225,11 @@ The code of the *SubscriberHelloWorldClient* is the following: uint8_t read_data_status; connected = mr_run_session_until_status(&session, MR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); } - + // Delete resources mr_delete_session(&session); mr_close_udp_transport(&transport); - + return 0; } From 378c2e8c269ba875863b0b2e285d5d9391472376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Wed, 26 Sep 2018 06:42:14 +0200 Subject: [PATCH 05/16] API changes updated. (#4) --- docs/client.rst | 32 +++++++++++++++++++++++++++++--- docs/getting_started.rst | 14 ++++++++------ docs/quickstart.rst | 8 ++++---- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index 9abc92a2..2236dab8 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -327,7 +327,7 @@ The function will return ``true`` if the sent data have been confirmed, ``false` .. code-block:: c - bool mr_run_session_until_status(mrSession* session, int timeout, const uint16_t* request_list, uint8_t* status_list, size_t list_size); + bool mr_run_session_until_all_status(mrSession* session, int timeout, const uint16_t* request_list, uint8_t* status_list, size_t list_size); The main library function. This function processes the internal functionality of a session. @@ -337,8 +337,8 @@ This implies: 2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. 3. Listenes messages from the agent and call the associated callback if exists (a topic callback or a status callback). -The ``_until_status`` suffix function version will perform these actions during ``timeout`` duration -or until the requested status had been received. +The ``_until_all_status`` suffix function version will perform these actions during ``timeout`` duration +or until all requested status had been received. The function will return ``true`` if all status have been received and all of them have the value ``MR_STATUS_OK`` or ``MR_STATUS_OK_MATCHED``, ``false`` otherwise. :session: Session structure previously initialized. @@ -351,6 +351,32 @@ The function will return ``true`` if all status have been received and all of th ------ +.. code-block:: c + + bool mr_run_session_until_one_status(mrSession* session, int timeout, const uint16_t* request_list, uint8_t* status_list, size_t list_size); + +The main library function. +This function processes the internal functionality of a session. +This implies: + +1. Flashes all output streams sending the data through the transport. +2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. +3. Listenes messages from the agent and call the associated callback if exists (a topic callback or a status callback). + +The ``_until_one_status`` suffix function version will perform these actions during ``timeout`` duration +or until one requested status had been received. +The function will return ``true`` if one status have been received and has the value ``MR_STATUS_OK`` or ``MR_STATUS_OK_MATCHED``, ``false`` otherwise. + +:session: Session structure previously initialized. +:timeout: Maximun time for waiting to a new message, in milliseconds. + For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` +:request_list: An array of request that can be confirmed. +:status_list: An uninitialized array with the same size as ``request_list`` where the statu value will be written. + The position of the status in the list corresponds to the request at the same position in ``request_list``. +:list_size: The size of ``request_list`` and ``status_list`` arrays. + +------ + Create entities by XML profile `````````````````````````````` These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` is enabled in the ``client.config`` file. diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 1a95e370..50dc87df 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -176,13 +176,13 @@ The different status values that the agent can send to the client are the follow MR_STATUS_ERR_INCOMPATIBLE MR_STATUS_ERR_RESOURCES -The status can be handle by the ``on_status_callback`` callback (configured in ``mr_set_status_callback`` function) or by the ``run_session_until_status`` as we will see. +The status can be handle by the ``on_status_callback`` callback (configured in ``mr_set_status_callback`` function) or by the ``run_session_until_all_status`` as we will see. .. code-block:: C uint8_t status[6]; // we have 6 request to check. uint16_t requests[6] = {participant_req, topic_req, publisher_req, subscriber_req, datawriter_req, datareader_req}; - if(!mr_run_session_until_status(&session, 1000, requests, status, 6)) + if(!mr_run_session_until_all_status(&session, 1000, requests, status, 6)) { printf("Error at create entities\n"); return 1; @@ -190,12 +190,14 @@ The status can be handle by the ``on_status_callback`` callback (configured in ` The ``run_session`` functions are the main functions of the `Micro RTP Client` library. They performs serveral things: send the stream data to the agent, listen data from the agent, call callbacks, and manage the reliable connection. -There are three variations of ``run_session`` function: +There are five variations of ``run_session`` function: +- ``mr_run_session_time`` - ``mr_run_session_until_timeout`` - ``mr_run_session_until_confirmed_delivery`` -- ``mr_run_session_until_status`` +- ``mr_run_session_until_all_status`` +- ``mr_run_session_until_one_status`` -Here we use the ``mr_run_session_until_status`` variation that will performs these actions until all status have been confirmed or the timeout has been reached. +Here we use the ``mr_run_session_until_all_status`` variation that will performs these actions until all status have been confirmed or the timeout has been reached. This function will return ``true`` in case all status were `OK`. After call this function, the status can be read from the ``status`` array previously declared. @@ -261,7 +263,7 @@ This id of the ``object_id`` corresponds to the DataReader that has read the Top The ``args`` argument correspond to user free data. Closing the Client -^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^ To close a *Client*, we must perform two steps. First, we need to tell the agent that the session is no longer available. This is done sending the next message: diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 220e0708..14d5436f 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -88,7 +88,7 @@ The code of the *PublishHelloWorldClient* is the following: // Send create entities message and wait its status uint8_t status[4]; uint16_t requests[4] = {participant_req, topic_req, publisher_req, datawriter_req}; - if(!mr_run_session_until_status(&session, 1000, requests, status, 4)) + if(!mr_run_session_until_all_status(&session, 1000, requests, status, 4)) { printf("Error at create entities: participant: %i topic: %i publisher: %i darawriter: %i\n", status[0], status[1], status[2], status[3]); return 1; @@ -106,7 +106,7 @@ The code of the *PublishHelloWorldClient* is the following: mr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); HelloWorld_serialize_topic(&mb, &topic); - connected = mr_run_session_until_timeout(&session, 1000); + connected = mr_run_session_until_time(&session, 1000); if(connected) { printf("Sent topic: %s, id: %i\n", topic.message, topic.index); @@ -207,7 +207,7 @@ The code of the *SubscriberHelloWorldClient* is the following: // Send create entities message and wait its status uint8_t status[4]; uint16_t requests[4] = {participant_req, topic_req, subscriber_req, datareader_req}; - if(!mr_run_session_until_status(&session, 1000, requests, status, 4)) + if(!mr_run_session_until_all_status(&session, 1000, requests, status, 4)) { printf("Error at create entities: participant: %i topic: %i subscriber: %i datareader: %i\n", status[0], status[1], status[2], status[3]); return 1; @@ -223,7 +223,7 @@ The code of the *SubscriberHelloWorldClient* is the following: while(connected && count < max_topics) { uint8_t read_data_status; - connected = mr_run_session_until_status(&session, MR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); + connected = mr_run_session_until_all_status(&session, MR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); } // Delete resources From e27d9b7d22e144d2cd567c209eaf1123406e41e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Thu, 27 Sep 2018 11:36:34 +0200 Subject: [PATCH 06/16] Refs #3436. Updated with MicroCDR prefix. (#5) --- docs/client.rst | 24 ++++++++++++------------ docs/gen.rst | 6 +++--- docs/getting_started.rst | 10 +++++----- docs/quickstart.rst | 4 ++-- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index 2236dab8..8c82c09e 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -580,20 +580,20 @@ The declaration of these function can be found in ``micrortps/client/profile/ses .. code-block:: c bool mr_prepare_output_stream(mrSession* session, mrStreamId stream_id, mrObjectId datawriter_id, - struct MicroBuffer* mb_topic, uint32_t topic_size); + struct mcBuffer* mb_topic, uint32_t topic_size); Requests a writing into a specific output stream. -For that this function will initialize a ``MicroBuffer`` struct where a topic of ``topic_size`` size must be serialized. +For that this function will initialize a ``mcBuffer`` struct where a topic of ``topic_size`` size must be serialized. If the returned value is ``true``, exists the necessary gap for writing a ``topic_size`` bytes into the stream. If the returned value is ``false``, the topic can no be serialized into the stream. The topic will be sent in the next ``run_session`` function. -NOTE: All `topic_size` bytes requested will be sent to the agent after a ``run_session`` call, no matter if the ``MicroBuffer`` has been used or not. +NOTE: All `topic_size` bytes requested will be sent to the agent after a ``run_session`` call, no matter if the ``mcBuffer`` has been used or not. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. :datawriter_id: The DataWriter ID that will write the topic to the DDS World. -:mb_topic: A ``MicroBuffer`` struct used to serialize the topic. +:mb_topic: A ``mcBuffer`` struct used to serialize the topic. This struct points to a requested gap into the stream. :topic_size: The bytes that will be reserved in the stream. @@ -609,24 +609,24 @@ The declaration of these function can be found in the generated file ``TOPICTYPE .. code-block:: c - bool TOPICTYPE_serialize_topic(struct MicroBuffer* writer, const TOPICTYPE* topic); + bool TOPICTYPE_serialize_topic(struct mcBuffer* writer, const TOPICTYPE* topic); -It serializes a topic into a MicroBuffer. +It serializes a topic into a mcBuffer. The returned value indicates if the serialization was successful. -:writer: A MicroBuffer representing the buffer for the serialization. +:writer: A mcBuffer representing the buffer for the serialization. :topic: Struct to serialize. ------ .. code-block:: c - bool TOPICTYPE_deserialize_topic(struct MicroBuffer* reader, TOPICTYPE* topic); + bool TOPICTYPE_deserialize_topic(struct mcBuffer* reader, TOPICTYPE* topic); -It deserializes a topic from a MicroBuffer. +It deserializes a topic from a mcBuffer. The returned value indicates if the serialization was successful. -:reader: A MicroBuffer representing the buffer for the deserialization. +:reader: A mcBuffer representing the buffer for the deserialization. :topic: Struct where deserialize. ------ @@ -635,10 +635,10 @@ The returned value indicates if the serialization was successful. uint32_t TOPICTYPE_size_of_topic(const TOPICTYPE* topic, uint32_t size); -It counts the number of bytes that the topic will need in a `MicroBuffer`. +It counts the number of bytes that the topic will need in a `mcBuffer`. :topic: Struct to count the size. -:size: Number of bytes already written into the `MicroBuffer`. +:size: Number of bytes already written into the `mcBuffer`. Typically its value is `0` if the purpose is to use in ``mr_prepare_output_stream`` function. ------ diff --git a/docs/gen.rst b/docs/gen.rst index b2f66106..16c5e9fa 100644 --- a/docs/gen.rst +++ b/docs/gen.rst @@ -55,10 +55,10 @@ it will generate the following header file and its corresponding source: } ShapeType; - struct MicroBuffer; + struct mcBuffer; - bool ShapeType_serialize_topic(struct MicroBuffer* writer, const ShapeType* topic); - bool ShapeType_deserialize_topic(struct MicroBuffer* reader, ShapeType* topic); + bool ShapeType_serialize_topic(struct mcBuffer* writer, const ShapeType* topic); + bool ShapeType_deserialize_topic(struct mcBuffer* reader, ShapeType* topic); uint32_t ShapeType_size_of_topic(const ShapeType* topic, uint32_t size); #endif // _ShapeType_H_ diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 50dc87df..9a015b31 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -210,7 +210,7 @@ For creating a message with data, first we must to decide which stream we want t HelloWorld topic = {count++, "Hello DDS world!"}; - MicroBuffer mb; + mcBuffer mb; uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0); (void) mr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); (void) HelloWorld_serialize_topic(&mb, &topic); @@ -220,9 +220,9 @@ For creating a message with data, first we must to decide which stream we want t ``HelloWorld_size_of_topic`` and ``HelloWorld_serialize_topic`` functions are automatically generated by :ref:`micrortpsgen_label` from the IDL. The function ``mr_prepare_output_stream`` requests a writing for a topic of ``topic_size`` size into the reliable stream represented by ``reliable_out``, with a ``datawriter_id`` (correspond to the data writer entity used for sending the data in the `DDS World`). -If the stream is available and the topic fits in it, the function will initialize the ``MicroBuffer`` structure ``mb``. -Once the ``MicroBuffer`` is prepared, the topic can be serialized into it. -We are careless about ``mr_prepare_output_stream`` return value because the serialization only will occur if the ``MicroBuffer` is valid`` +If the stream is available and the topic fits in it, the function will initialize the ``mcBuffer`` structure ``mb``. +Once the ``mcBuffer`` is prepared, the topic can be serialized into it. +We are careless about ``mr_prepare_output_stream`` return value because the serialization only will occur if the ``mcBuffer` is valid`` After the write function, as happend with the creation of entities, the topic has been serialized into the buffer but it has not been sent yet. To send the topic is necessary call to a ``run_session`` function. @@ -250,7 +250,7 @@ The ``run_session`` function will call the topic callback each time a topic will .. code-block:: C - void on_topic(mrSession* session, mrObjectId object_id, uint16_t request_id, mrStreamId stream_id, struct MicroBuffer* mb, void* args) + void on_topic(mrSession* session, mrObjectId object_id, uint16_t request_id, mrStreamId stream_id, struct mcBuffer* mb, void* args) { (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) args; diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 14d5436f..eb2d18b4 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -101,7 +101,7 @@ The code of the *PublishHelloWorldClient* is the following: { HelloWorld topic = {count++, "Hello DDS world!"}; - MicroBuffer mb; + mcBuffer mb; uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0); mr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); HelloWorld_serialize_topic(&mb, &topic); @@ -138,7 +138,7 @@ The code of the *SubscriberHelloWorldClient* is the following: #define STREAM_HISTORY 8 #define BUFFER_SIZE MR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY - void on_topic(mrSession* session, mrObjectId object_id, uint16_t request_id, mrStreamId stream_id, struct MicroBuffer* mb, void* args) + void on_topic(mrSession* session, mrObjectId object_id, uint16_t request_id, mrStreamId stream_id, struct mcBuffer* mb, void* args) { (void) session; (void) object_id; (void) request_id; (void) stream_id; From 77ebf1e1965847d689d401642a84bb1c9e072c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Tue, 9 Oct 2018 10:29:07 +0200 Subject: [PATCH 07/16] Product name changed: RTPS to XRCE-DDS (#6) * Refs #3451. Updated RTPS occurrences to XRCE-DDS * Refs #3451. Updated rtps occurrences to xrce-dds or xrce_dds * Modified images for new name. * Updated code with the name changes. --- README.md | 14 +- docs/agent.rst | 14 +- docs/client.rst | 206 +++++++++++++-------------- docs/conf.py | 12 +- docs/dependencies.rst | 12 +- docs/deployment.rst | 4 +- docs/entities.rst | 6 +- docs/gen.rst | 30 ++-- docs/getting_started.rst | 128 ++++++++--------- docs/images/architecture.png | Bin 22721 -> 0 bytes docs/images/architecture.svg | 2 - docs/images/entities_hierarchy.svg | 2 +- docs/images/xrcedds_architecture.svg | 2 + docs/index.rst | 36 ++--- docs/installation.rst | 22 +-- docs/introduction.rst | 20 +-- docs/operations.rst | 6 +- docs/quickstart.rst | 112 +++++++-------- docs/shapes_demo.rst | 2 +- 19 files changed, 315 insertions(+), 315 deletions(-) delete mode 100644 docs/images/architecture.png delete mode 100644 docs/images/architecture.svg create mode 100644 docs/images/xrcedds_architecture.svg diff --git a/README.md b/README.md index c6cca334..706ce2d8 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# eProsima Micro RTPS +# eProsima Micro XRCE-DDS -*eProsima Micro RTPS* is a software solution which allows to communicate eXtremely Resource Constrained Environments (XRCEs) with an existing DDS network. This implementation complies with the specification proposal, "eXtremely Resource Constrained Environments DDS (DDS-XRCE)" submitted to the Object Management Group (OMG) consortium. +*eProsima Micro XRCE-DDS* is a software solution which allows to communicate eXtremely Resource Constrained Environments (XRCEs) with an existing DDS network. This implementation complies with the specification proposal, "eXtremely Resource Constrained Environments DDS (DDS-XRCE)" submitted to the Object Management Group (OMG) consortium. -*Micro RTPS* implements a client-server protocol to enable resource-constrained devices (clients) to take part in DDS communications. *Micro RTPS Agent* (server) makes possible this communication. The *Micro RTPS Agent* acts on behalf of the *Micro RTPS Clients* and enables them to take part as DDS publishers and/or subscribers in the DDS Global Data Space. +*Micro XRCE-DDS* implements a client-server protocol to enable resource-constrained devices (clients) to take part in DDS communications. *Micro XRCE-DDS Agent* (server) makes possible this communication. The *Micro XRCE-DDS Agent* acts on behalf of the *Micro XRCE-DDS Clients* and enables them to take part as DDS publishers and/or subscribers in the DDS Global Data Space. -*Micro RTPS* provides both, a plug and play *Micro RTPS Agent* and an API layer which allows you to implement your *Micro RTPS Clients*. +*Micro XRCE-DDS* provides both, a plug and play *Micro XRCE-DDS Agent* and an API layer which allows you to implement your *Micro XRCE-DDS Clients*. ![Architecture](docs/architecture.png) @@ -14,9 +14,9 @@ You can access the documentation online, which is hosted on Read the Docs. -* [Start Page](http://micro-rtps.readthedocs.io) -* [Installation manual](http://micro-rtps.readthedocs.io/en/latest/installation.html) -* [User manual](http://micro-rtps.readthedocs.io/en/latest/introduction.html) +* [Start Page](http://micro-xrce-dds.readthedocs.io) +* [Installation manual](http://micro-xrce-dds.readthedocs.io/en/latest/installation.html) +* [User manual](http://micro-xrce-dds.readthedocs.io/en/latest/introduction.html) ## Getting Help diff --git a/docs/agent.rst b/docs/agent.rst index fabc16ee..c4782ee0 100644 --- a/docs/agent.rst +++ b/docs/agent.rst @@ -1,9 +1,9 @@ -.. _micro_rtps_agent_label: +.. _micro_xrce_dds_agent_label: -Micro RTPS Agent -================ +Micro XRCE-DDS Agent +==================== -*Micro RTPS Agent* acts as a server between the DDS Network and *Micro RTPS Clients*. +*Micro XRCE-DDS Agent* acts as a server between the DDS Network and *Micro XRCE-DDS Clients*. Agents receive messages containing operations from clients. Also agents keep track of the clients and the entities they create. The Agent uses the entities to interact with the DDS Global Data Space on behalf of the client. @@ -19,15 +19,15 @@ Once it is built successfully you just need to launch it executing the following For serial communication: :: - $ ./MicroRTPSAgent serial + $ ./MicroXRCE-DDSAgent serial For udp communication: :: - $ ./MicroRTPSAgent udp + $ ./MicroXRCE-DDSAgent udp For tcp communication: :: - $ ./MicroRTPSAgent tcp + $ ./MicroXRCE-DDSAgent tcp If the transport used is a reliability transport, the use of a best effort stream over it is equivalent to use a reliable stream over a not reliable transport. diff --git a/docs/client.rst b/docs/client.rst index 8c82c09e..ba258afd 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -1,11 +1,11 @@ -.. _micro_rtps_client_label: +.. _micro_xrce_dds_client_label: -Micro RTPS Client -================= -In *Micro RTPS*, a *Client* can communicate with DDS Network as any other DDS actor could do. +Micro XRCE-DDS Client +===================== +In *Micro XRCE-DDS*, a *Client* can communicate with DDS Network as any other DDS actor could do. *Clients* can publish and subscribe to data Topics in the DDS Global Data Space. -*Micro RTPS* provides you with a C API to create *Micro RTPS Clients*. +*Micro XRCE-DDS* provides you with a C API to create *Micro XRCE-DDS Clients*. All functions needed to set up the *Client* can be found into ``client.h`` header. This is the only header you need to include. @@ -29,7 +29,7 @@ TCP X X X Serial X X ============ ========== ========= ========= -The addition of a new transport or an existant transport for a new platform can be easily implemented setting the callbacks of a ``mrCommunication`` structure. +The addition of a new transport or an existant transport for a new platform can be easily implemented setting the callbacks of a ``uxrCommunication`` structure. See the current transport implementations as an example for a new custom transport. Configuration @@ -62,19 +62,19 @@ For incorporating the changes to your project, is necessary to run the ``cmake`` ``CONFIG_MAX_OUTPUT_BEST_EFFORT_STREAMS=`` Configures the maximun output best effort streams that a session could have. - The calls to ``mr_create_output_best_effort_stream`` function for a session must be less or equal that this value. + The calls to ``uxr_create_output_best_effort_stream`` function for a session must be less or equal that this value. ``CONFIG_MAX_OUTPUT_RELIABLE_STREAMS=`` Configures the maximun output reliable streams that a session could have. - The calls to ``mr_create_output_reliable_stream`` function for a session must be less or equal that this value. + The calls to ``uxr_create_output_reliable_stream`` function for a session must be less or equal that this value. ``CONFIG_MAX_INPUT_BEST_EFFORT_STREAMS=`` Configure the maximun input best effort streams that a session could have. - The calls to ``mr_create_input_best_effort_stream`` function for a session must be less or equal that this value. + The calls to ``uxr_create_input_best_effort_stream`` function for a session must be less or equal that this value. ``CONFIG_MAX_INPUT_RELIABLE_STREAMS=`` Configures the maximun input reliable streams that a session could have. - The calls to ``mr_create_input_reliable_stream`` function for a session must be less or equal that this value. + The calls to ``uxr_create_input_reliable_stream`` function for a session must be less or equal that this value. ``CONFIG_MAX_SESSION_CONNECTION_ATTEMPTS=`` This value indicates the number of attempts that ``create_session`` and ``delete_session`` will perform until receiving an status message. @@ -110,21 +110,21 @@ For incorporating the changes to your project, is necessary to run the ``cmake`` API --- -As a nomenclature, `Micro RTPS Client` API uses a ``mr_`` prefix in all of their public API functions and ``mr`` prefix in the types. -In constants values an ``MR_`` prefix is used. +As a nomenclature, `Micro XRCE-DDS Client` API uses a ``uxr_`` prefix in all of their public API functions and ``uxr`` prefix in the types. +In constants values an ``UXR_`` prefix is used. Functions without these rules `should not` be used. They are only for internal use. Session ``````` These functions are available even if no profile has been enabled in ``client.config`` file. -The declaration of these function can be found in ``micrortps/client/core/session/session.h``. +The declaration of these function can be found in ``uxr/client/core/session/session.h``. ------ .. code-block:: c - void mr_init_session(mrSession* session, mrCommunication* comm, uint32_t key); + void uxr_init_session(uxrSession* session, uxrCommunication* comm, uint32_t key); Initializes a session structure. Once this function is called, a ``create_session`` call can be performed. @@ -133,14 +133,14 @@ Once this function is called, a ``create_session`` call can be performed. :key: The identifying key of the client. All clients connected to an agent must have different key. :comm: Communication used for connecting to the agent. - All different transports have a common attribute mrCommunication. + All different transports have a common attribute uxrCommunication. This parameter can not be shared between active sessions. ------ .. code-block:: c - void mr_set_status_callback(mrSession* session, mrOnStatusFunc on_status_func, void* args); + void uxr_set_status_callback(uxrSession* session, uxrOnStatusFunc on_status_func, void* args); Assigns the callback for the agent status messages. @@ -153,7 +153,7 @@ Assigns the callback for the agent status messages. .. code-block:: c - void mr_set_topic_callback(mrSession* session, mrOnTopicFunc on_topic_func, void* args); + void uxr_set_topic_callback(uxrSession* session, uxrOnTopicFunc on_topic_func, void* args); Assigns the callback for topics. The topics will be received only if a ``request_data`` function has been called. @@ -167,7 +167,7 @@ The topics will be received only if a ``request_data`` function has been called. .. code-block:: c - bool mr_create_session(mrSession* session); + bool uxr_create_session(uxrSession* session); Creates a new session with the agent. This function logs in a session, enabling any other XRCE communication with the agent. @@ -178,7 +178,7 @@ This function logs in a session, enabling any other XRCE communication with the .. code-block:: c - bool mr_delete_session(mrSession* session); + bool uxr_delete_session(uxrSession* session); Deletes session previously created. All `XRCE` entities created with the session will be removed. @@ -190,10 +190,10 @@ This function logs out a session, disabling any other `XRCE` communication with .. code-block:: c - mrStreamId mr_create_output_best_effort_stream(mrSession* session, uint8_t* buffer, size_t size); + uxrStreamId uxr_create_output_best_effort_stream(uxrSession* session, uint8_t* buffer, size_t size); Creates and initializes an output best effort stream for writing. -The ``mrStreamId`` returned represents the new stream and can be used to manage it. +The ``uxrStreamId`` returned represents the new stream and can be used to manage it. The number of available calls to this function must be less or equal than ``CONFIG_MAX_OUTPUT_BEST_EFFORT_STREAMS`` value of the ``client.config`` file. :session: Session structure previously initialized. @@ -204,10 +204,10 @@ The number of available calls to this function must be less or equal than ``CONF .. code-block:: c - mrStreamId mr_create_output_reliable_stream(mrSession* session, uint8_t* buffer, size_t size, size_t history); + uxrStreamId uxr_create_output_reliable_stream(uxrSession* session, uint8_t* buffer, size_t size, size_t history); Creates and initializes an output reliable stream for writing. -The ``mrStreamId`` returned represents the new stream and can be used to manage it. +The ``uxrStreamId`` returned represents the new stream and can be used to manage it. The number of available calls to this function must be less or equal than ``CONFIG_MAX_OUTPUT_RELIABLE_STREAMS`` value of the ``client.config`` file. :session: Session structure previously initialized. @@ -221,10 +221,10 @@ The number of available calls to this function must be less or equal than ``CONF .. code-block:: c - mrStreamId mr_create_input_best_effort_stream(mrSession* session); + uxrStreamId uxr_create_input_best_effort_stream(uxrSession* session); Creates and initializes an input best effort stream for receiving messages. -The ``mrStreamId`` returned represents the new stream and can be used to manage it. +The ``uxrStreamId`` returned represents the new stream and can be used to manage it. The number of available calls to this function must be less or equal than ``CONFIG_MAX_INPUT_BEST_EFFORT_STREAMS`` value of the ``client.config`` file. :session: Session structure previously initialized. @@ -233,10 +233,10 @@ The number of available calls to this function must be less or equal than ``CONF .. code-block:: c - mrStreamId mr_create_input_reliable_stream(mrSession* session, uint8_t* buffer, size_t size, size_t history); + uxrStreamId uxr_create_input_reliable_stream(uxrSession* session, uint8_t* buffer, size_t size, size_t history); Creates and initializes an input reliable stream for receiving messages. -The returned ``mrStreamId`` represents the new stream and can be used to manage it. +The returned ``uxrStreamId`` represents the new stream and can be used to manage it. The number of available calls to this function must be less or equal than ``CONFIG_MAX_INPUT_RELIABLE_STREAMS`` value of the ``client.config`` file. :session: Session structure previously initialized. @@ -250,7 +250,7 @@ The number of available calls to this function must be less or equal than ``CONF .. code-block:: c - void mr_flash_output_streams(mrSession* session); + void uxr_flash_output_streams(uxrSession* session); Flashes all output streams sending the data through the transport. @@ -260,7 +260,7 @@ Flashes all output streams sending the data through the transport. .. code-block:: c - void mr_run_session_time(mrSession* session, int time); + void uxr_run_session_time(uxrSession* session, int time); The main library function. This function processes the internal functionality of a session. @@ -276,13 +276,13 @@ The function will return ``true`` if the sent data have been confirmed, ``false` :session: Session structure previously initialized. :time: Time for waiting, in milliseconds. - For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` + For waiting without timeout, set the value to ``UXR_TIMEOUT_INF`` ------ .. code-block:: c - void mr_run_session_until_timeout(mrSession* session, int timeout); + void uxr_run_session_until_timeout(uxrSession* session, int timeout); The main library function. This function processes the internal functionality of a session. @@ -299,13 +299,13 @@ The function will return ``true`` if has received a message, ``false`` if the ti :session: Session structure previously initialized. :timeout: Time for waiting a new message, in milliseconds. - For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` + For waiting without timeout, set the value to ``UXR_TIMEOUT_INF`` ------ .. code-block:: c - bool mr_run_session_until_confirm_delivery(mrSession* session, int timeout); + bool uxr_run_session_until_confirm_delivery(uxrSession* session, int timeout); The main library function. This function processes the internal functionality of a session. @@ -321,13 +321,13 @@ The function will return ``true`` if the sent data have been confirmed, ``false` :session: Session structure previously initialized. :timeout: Maximun time for waiting to a new message, in milliseconds. - For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` + For waiting without timeout, set the value to ``UXR_TIMEOUT_INF`` ------ .. code-block:: c - bool mr_run_session_until_all_status(mrSession* session, int timeout, const uint16_t* request_list, uint8_t* status_list, size_t list_size); + bool uxr_run_session_until_all_status(uxrSession* session, int timeout, const uint16_t* request_list, uint8_t* status_list, size_t list_size); The main library function. This function processes the internal functionality of a session. @@ -339,11 +339,11 @@ This implies: The ``_until_all_status`` suffix function version will perform these actions during ``timeout`` duration or until all requested status had been received. -The function will return ``true`` if all status have been received and all of them have the value ``MR_STATUS_OK`` or ``MR_STATUS_OK_MATCHED``, ``false`` otherwise. +The function will return ``true`` if all status have been received and all of them have the value ``UXR_STATUS_OK`` or ``UXR_STATUS_OK_MATCHED``, ``false`` otherwise. :session: Session structure previously initialized. :timeout: Maximun time for waiting to a new message, in milliseconds. - For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` + For waiting without timeout, set the value to ``UXR_TIMEOUT_INF`` :request_list: An array of request to confirm with a status. :status_list: An uninitialized array with the same size as ``request_list`` where the status values will be written. The position of a status in the list corresponds to the request at the same position in ``request_list``. @@ -353,7 +353,7 @@ The function will return ``true`` if all status have been received and all of th .. code-block:: c - bool mr_run_session_until_one_status(mrSession* session, int timeout, const uint16_t* request_list, uint8_t* status_list, size_t list_size); + bool uxr_run_session_until_one_status(uxrSession* session, int timeout, const uint16_t* request_list, uint8_t* status_list, size_t list_size); The main library function. This function processes the internal functionality of a session. @@ -365,11 +365,11 @@ This implies: The ``_until_one_status`` suffix function version will perform these actions during ``timeout`` duration or until one requested status had been received. -The function will return ``true`` if one status have been received and has the value ``MR_STATUS_OK`` or ``MR_STATUS_OK_MATCHED``, ``false`` otherwise. +The function will return ``true`` if one status have been received and has the value ``UXR_STATUS_OK`` or ``UXR_STATUS_OK_MATCHED``, ``false`` otherwise. :session: Session structure previously initialized. :timeout: Maximun time for waiting to a new message, in milliseconds. - For waiting without timeout, set the value to ``MR_TIMEOUT_INF`` + For waiting without timeout, set the value to ``UXR_TIMEOUT_INF`` :request_list: An array of request that can be confirmed. :status_list: An uninitialized array with the same size as ``request_list`` where the statu value will be written. The position of the status in the list corresponds to the request at the same position in ``request_list``. @@ -380,13 +380,13 @@ The function will return ``true`` if one status have been received and has the v Create entities by XML profile `````````````````````````````` These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` is enabled in the ``client.config`` file. -The declaration of these function can be found in ``micrortps/client/profile/session/create_entities_xml.h``. +The declaration of these function can be found in ``uxr/client/profile/session/create_entities_xml.h``. ------ .. code-block:: c - uint16_t mr_write_configure_participant_xml(mrSession* session, mrStreamId stream_id, mrObjectId object_id, uint16_t domain, const char* xml, uint8_t mode); + uint16_t uxr_write_configure_participant_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uint16_t domain, const char* xml, uint8_t mode); Create a `participant` entity in the agent. @@ -394,10 +394,10 @@ Create a `participant` entity in the agent. :stream_id: The output stream ID where the message will be written. :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. - The type must be ``MR_PARTICIPANT_ID`` + The type must be ``UXR_PARTICIPANT_ID`` :xml: A xml representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``MR_REPLACE``. + Currently, only soported ``UXR_REPLACE``. It will delete the entity previously in the agent if exists. A ``0`` value, implies that only creates the entity if it does not exists. @@ -405,7 +405,7 @@ Create a `participant` entity in the agent. .. code-block:: c - uint16_t mr_write_configure_topic_xml(mrSession* session, mrStreamId stream_id, mrObjectId object_id, mrObjectId participant_id, const char* xml, uint8_t mode); + uint16_t uxr_write_configure_topic_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); Create a `topic` entity in the agent. @@ -413,10 +413,10 @@ Create a `topic` entity in the agent. :stream_id: The output stream ID where the message will be written. :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. - The type must be ``MR_TOPIC_ID`` + The type must be ``UXR_TOPIC_ID`` :xml: A xml representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``MR_REPLACE``. + Currently, only soported ``UXR_REPLACE``. It will delete the entity previously in the agent if exists. A ``0`` value, implies that only creates the entity if it does not exists. @@ -424,7 +424,7 @@ Create a `topic` entity in the agent. .. code-block:: c - uint16_t mr_write_configure_publisher_xml(mrSession* session, mrStreamId stream_id, mrObjectId object_id, mrObjectId participant_id, const char* xml, uint8_t mode); + uint16_t uxr_write_configure_publisher_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); Create a `publisher` entity in the agent. @@ -432,10 +432,10 @@ Create a `publisher` entity in the agent. :stream_id: The output stream ID where the message will be written. :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. - The type must be ``MR_PUBLISHER_ID`` + The type must be ``UXR_PUBLISHER_ID`` :xml: A xml representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``MR_REPLACE``. + Currently, only soported ``UXR_REPLACE``. It will delete the entity previously in the agent if exists. A ``0`` value, implies that only creates the entity if it does not exists. @@ -443,7 +443,7 @@ Create a `publisher` entity in the agent. .. code-block:: c - uint16_t mr_write_configure_subscriber_xml(mrSession* session, mrStreamId stream_id, mrObjectId object_id, mrObjectId participant_id, const char* xml, uint8_t mode); + uint16_t uxr_write_configure_subscriber_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); Create a `publisher` entity in the agent. @@ -451,10 +451,10 @@ Create a `publisher` entity in the agent. :stream_id: The output stream ID where the message will be written. :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. - The type must be ``MR_SUBSCRIBER_ID`` + The type must be ``UXR_SUBSCRIBER_ID`` :xml: A xml representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``MR_REPLACE``. + Currently, only soported ``UXR_REPLACE``. It will delete the entity previously in the agent if exists. A ``0`` value, implies that only creates the entity if it does not exists. @@ -462,7 +462,7 @@ Create a `publisher` entity in the agent. .. code-block:: c - uint16_t mr_write_configure_datawriter_xml(mrSession* session, mrStreamId stream_id, mrObjectId object_id, mrObjectId publisher_id, const char* xml, uint8_t mode); + uint16_t uxr_write_configure_datawriter_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId publisher_id, const char* xml, uint8_t mode); Create a `datawriter_id` entity in the agent. @@ -470,10 +470,10 @@ Create a `datawriter_id` entity in the agent. :stream_id: The output stream ID where the message will be written. :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. - The type must be ``MR_DATAWRITER_ID`` + The type must be ``UXR_DATAWRITER_ID`` :xml: A xml representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``MR_REPLACE``. + Currently, only soported ``UXR_REPLACE``. It will delete the entity previously in the agent if exists. A ``0`` value, implies that only creates the entity if it does not exists. @@ -481,7 +481,7 @@ Create a `datawriter_id` entity in the agent. .. code-block:: c - uint16_t mr_write_configure_datareader_xml(mrSession* session, mrStreamId stream_id, mrObjectId object_id, mrObjectId subscriber_id, const char* xml, uint8_t mode); + uint16_t uxr_write_configure_datareader_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId subscriber_id, const char* xml, uint8_t mode); Create a `datareader` entity in the agent. @@ -489,10 +489,10 @@ Create a `datareader` entity in the agent. :stream_id: The output stream ID where the message will be written. :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. - The type must be ``MR_DATAREADER_ID`` + The type must be ``UXR_DATAREADER_ID`` :xml: A xml representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``MR_REPLACE``. + Currently, only soported ``UXR_REPLACE``. It will delete the entity previously in the agent if exists. A ``0`` value, implies that only creates the entity if it does not exists. @@ -501,13 +501,13 @@ Create a `datareader` entity in the agent. Create entities by reference profile ```````````````````````````````````` These functions are enabled when ``PROFILE_CREATE_ENTITIES_REF`` is enabled in the ``client.config`` file. -The declaration of these function can be found in ``micrortps/client/profile/session/create_entities_ref.h``. +The declaration of these function can be found in ``uxr/client/profile/session/create_entities_ref.h``. ------ .. code-block:: c - uint16_t mr_write_create_participant_ref(mrSession* session, mrStreamId stream_id, mrObjectId object_id, const char* ref, uint8_t mode); + uint16_t uxr_write_create_participant_ref(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, const char* ref, uint8_t mode); Create a `datareader` entity in the agent. @@ -515,10 +515,10 @@ Create a `datareader` entity in the agent. :stream_id: The output stream ID where the message will be written. :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. - The type must be ``MR_DATAREADER_ID`` + The type must be ``UXR_DATAREADER_ID`` :xml: A xml representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``MR_REPLACE``. + Currently, only soported ``UXR_REPLACE``. It will delete the entity previously in the agent if exists. A ``0`` value, implies that only creates the entity if it does not exists. @@ -527,13 +527,13 @@ Create a `datareader` entity in the agent. Create entities common profile `````````````````````````````` These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` or ``PROFILE_CREATE_ENTITIES_REF`` are enabled in the ``client.config`` file. -The declaration of these function can be found in ``micrortps/client/profile/session/common_create_entities.h``. +The declaration of these function can be found in ``uxr/client/profile/session/common_create_entities.h``. ------ .. code-block:: c - uint16_t mr_write_delete_entity(mrSession* session, mrStreamId stream_id, mrObjectId object_id); + uint16_t uxr_write_delete_entity(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id); Removes a entity. @@ -546,19 +546,19 @@ Removes a entity. Read access profile ``````````````````` These functions are enabled when PROFILE_READ_ACCESS is enabled in the ``client.config`` file. -The declaration of these function can be found in ``micrortps/client/profile/session/read_access.h``. +The declaration of these function can be found in ``uxr/client/profile/session/read_access.h``. ------ .. code-block:: c - uint16_t mr_write_request_data(mrSession* session, mrStreamId stream_id, mrObjectId datareader_id, mrStreamId data_stream_id, mrDeliveryControl* delivery_control); + uint16_t uxr_write_request_data(uxrSession* session, uxrStreamId stream_id, uxrObjectId datareader_id, uxrStreamId data_stream_id, uxrDeliveryControl* delivery_control); This function requests a read from a datareader of the agent. The returned value is an identifier of the request. All received topic will have the same request identifier. The topics will be received at the callback topic through the ``run_session`` function. -If there is no error with the request data, the topics will be received generating a status callback with the value ``MR_STATUS_OK``. +If there is no error with the request data, the topics will be received generating a status callback with the value ``UXR_STATUS_OK``. If there is an error, a status error will be sent by the agent. :session: Session structure previously initialized. @@ -573,27 +573,27 @@ If there is an error, a status error will be sent by the agent. Write access profile ```````````````````` These functions are enabled when PROFILE_WRITE_ACCESS is enabled in the ``client.config`` file. -The declaration of these function can be found in ``micrortps/client/profile/session/write_access.h``. +The declaration of these function can be found in ``uxr/client/profile/session/write_access.h``. ------ .. code-block:: c - bool mr_prepare_output_stream(mrSession* session, mrStreamId stream_id, mrObjectId datawriter_id, - struct mcBuffer* mb_topic, uint32_t topic_size); + bool uxr_prepare_output_stream(uxrSession* session, uxrStreamId stream_id, uxrObjectId datawriter_id, + struct ucdrBuffer* mb_topic, uint32_t topic_size); Requests a writing into a specific output stream. -For that this function will initialize a ``mcBuffer`` struct where a topic of ``topic_size`` size must be serialized. +For that this function will initialize a ``ucdrBuffer`` struct where a topic of ``topic_size`` size must be serialized. If the returned value is ``true``, exists the necessary gap for writing a ``topic_size`` bytes into the stream. If the returned value is ``false``, the topic can no be serialized into the stream. The topic will be sent in the next ``run_session`` function. -NOTE: All `topic_size` bytes requested will be sent to the agent after a ``run_session`` call, no matter if the ``mcBuffer`` has been used or not. +NOTE: All `topic_size` bytes requested will be sent to the agent after a ``run_session`` call, no matter if the ``ucdrBuffer`` has been used or not. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. :datawriter_id: The DataWriter ID that will write the topic to the DDS World. -:mb_topic: A ``mcBuffer`` struct used to serialize the topic. +:mb_topic: A ``ucdrBuffer`` struct used to serialize the topic. This struct points to a requested gap into the stream. :topic_size: The bytes that will be reserved in the stream. @@ -602,31 +602,31 @@ NOTE: All `topic_size` bytes requested will be sent to the agent after a ``run_s Topic serialization ``````````````````` Functions to serialize and deserialize topics. -These functions are generated automatically by `MicroRTPSGen` utility over an idl file with a topic `TOPICTYPE`. +These functions are generated automatically by `Micro XRCE-DDS Gen` utility over an idl file with a topic `TOPICTYPE`. The declaration of these function can be found in the generated file ``TOPICTYPE.h``. ------ .. code-block:: c - bool TOPICTYPE_serialize_topic(struct mcBuffer* writer, const TOPICTYPE* topic); + bool TOPICTYPE_serialize_topic(struct ucdrBuffer* writer, const TOPICTYPE* topic); -It serializes a topic into a mcBuffer. +It serializes a topic into a ucdrBuffer. The returned value indicates if the serialization was successful. -:writer: A mcBuffer representing the buffer for the serialization. +:writer: A ucdrBuffer representing the buffer for the serialization. :topic: Struct to serialize. ------ .. code-block:: c - bool TOPICTYPE_deserialize_topic(struct mcBuffer* reader, TOPICTYPE* topic); + bool TOPICTYPE_deserialize_topic(struct ucdrBuffer* reader, TOPICTYPE* topic); -It deserializes a topic from a mcBuffer. +It deserializes a topic from a ucdrBuffer. The returned value indicates if the serialization was successful. -:reader: A mcBuffer representing the buffer for the deserialization. +:reader: A ucdrBuffer representing the buffer for the deserialization. :topic: Struct where deserialize. ------ @@ -635,37 +635,37 @@ The returned value indicates if the serialization was successful. uint32_t TOPICTYPE_size_of_topic(const TOPICTYPE* topic, uint32_t size); -It counts the number of bytes that the topic will need in a `mcBuffer`. +It counts the number of bytes that the topic will need in a `ucdrBuffer`. :topic: Struct to count the size. -:size: Number of bytes already written into the `mcBuffer`. - Typically its value is `0` if the purpose is to use in ``mr_prepare_output_stream`` function. +:size: Number of bytes already written into the `ucdrBuffer`. + Typically its value is `0` if the purpose is to use in ``uxr_prepare_output_stream`` function. ------ General utilities ````````````````` Utility functions. -The declaration of these functions can be found in ``micrortps/client/core/session/stream_id.h`` and ``micrortps/client/core/session/object_id.h``. +The declaration of these functions can be found in ``uxr/client/core/session/stream_id.h`` and ``uxr/client/core/session/object_id.h``. ------ .. code-block:: c - mrStreamId mr_stream_id(uint8_t index, mrStreamType type, mrStreamDirection direction); + uxrStreamId uxr_stream_id(uint8_t index, uxrStreamType type, uxrStreamDirection direction); Creates an stream identifier. This function does not create a new stream, only creates its identifier to be used in the `Client` API. :index: Identifier of the stream, its value correspond to the creation order of the stream, different for each `type`. -:type: The type of the stream, it can be MR_BEST_EFFORT_STREAM or MR_RELIABLE_STREAM. -:direction: Represents the direccion of the stream, it can be MR_INPUT_STREAM or MT_OUTPUT_STREAM. +:type: The type of the stream, it can be UXR_BEST_EFFORT_STREAM or UXR_RELIABLE_STREAM. +:direction: Represents the direccion of the stream, it can be UXR_INPUT_STREAM or MT_OUTPUT_STREAM. ------ .. code-block:: c - mrStreamId mr_stream_id_from_raw(uint8_t stream_id_raw, mrStreamDirection direction); + uxrStreamId uxr_stream_id_from_raw(uint8_t stream_id_raw, uxrStreamDirection direction); Creates an stream identifier. This function does not create a new stream, only creates its identifier to be used in the `Client` API. @@ -675,13 +675,13 @@ This function does not create a new stream, only creates its identifier to be us 0 is for internal library use. 1 to 127, for best effort. 128 to 255, for reliable. -:direction: Represents the direccion of the stream, it can be MR_INPUT_STREAM or MT_OUTPUT_STREAM. +:direction: Represents the direccion of the stream, it can be UXR_INPUT_STREAM or MT_OUTPUT_STREAM. ------ .. code-block:: c - mrObjectId mr_object_id(uint16_t id, uint8_t type); + uxrObjectId uxr_object_id(uint16_t id, uint8_t type); Creates a identifier for reference an entity. @@ -689,12 +689,12 @@ Creates a identifier for reference an entity. (Can be several ids with the same id if they have different types) :type: The type of the entity. It can be: - * MR_PARTICIPANT_ID - * MR_TOPIC_ID - * MR_PUBLISHER_ID - * MR_SUBSCRIBER_ID - * MR_DATAWRITER_ID - * MR_DATAREADER_ID + * UXR_PARTICIPANT_ID + * UXR_TOPIC_ID + * UXR_PUBLISHER_ID + * UXR_SUBSCRIBER_ID + * UXR_DATAWRITER_ID + * UXR_DATAREADER_ID ------ @@ -702,14 +702,14 @@ Transport ````````` These functions are platform dependent. The values ``PROFILE_XXX_TRANSPORT`` found into ``client.config`` allow to enable some of them. -The declaration of these function can be found in ``micrortps/client/profile/transport/`` folder. +The declaration of these function can be found in ``uxr/client/profile/transport/`` folder. The common init transport functions follow the next nomenclature. ------ .. code-block:: c - bool mr_init_udp_transport(UDPTransport* transport, const char* ip, uint16_t port); + bool uxr_init_udp_transport(UDPTransport* transport, const char* ip, uint16_t port); Initializes an UDP connection. @@ -722,7 +722,7 @@ Initializes an UDP connection. .. code-block:: c - bool mr_init_tcp_transport(TCPTransport* transport, const char* ip, uint16_t port); + bool uxr_init_tcp_transport(TCPTransport* transport, const char* ip, uint16_t port); Initializes a TCP connection. If the TCP is used, the behaviour of best effort streams will be similiar to reliable streams in UDP. @@ -736,7 +736,7 @@ If the TCP is used, the behaviour of best effort streams will be similiar to rel .. code-block:: c - bool mr_init_serial_transport(SerialTransport* transport, const char* device, uint8_t remote_addr, uint8_t local_addr); + bool uxr_init_serial_transport(SerialTransport* transport, const char* device, uint8_t remote_addr, uint8_t local_addr); Initializes a Serial connection using a device. @@ -751,7 +751,7 @@ Initializes a Serial connection using a device. .. code-block:: c - bool mr_init_serial_transport_fd(SerialTransport* transport, const int fd, uint8_t remote_addr, uint8_t local_addr); + bool uxr_init_serial_transport_fd(SerialTransport* transport, const int fd, uint8_t remote_addr, uint8_t local_addr); Initializes a Serial connection using a file descriptor @@ -766,7 +766,7 @@ Initializes a Serial connection using a file descriptor .. code-block:: c - bool mr_close_PROTOCOL_transport(PROTOCOLTransport* transport); + bool uxr_close_PROTOCOL_transport(PROTOCOLTransport* transport); Closes a transport previously opened. `PROTOCOL` can be ``udp``, ``tcp`` or ``serial``. diff --git a/docs/conf.py b/docs/conf.py index 32a70a37..1052cb9d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,7 +48,7 @@ master_doc = 'index' # General information about the project. -project = u'Micro RTPS' +project = u'Micro XRCE-DDS' copyright = u'2017, eProsima' author = u'eProsima' @@ -240,7 +240,7 @@ # html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'MicroRTPSManual' +htmlhelp_basename = 'MicroXRCE-DDSManual' # -- Options for LaTeX output --------------------------------------------- @@ -266,7 +266,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'MicroRTPS.tex', u'MicroRTPS Documentation', + (master_doc, 'MicroXRCE-DDS.tex', u'MicroXRCE-DDS Documentation', u'eProsima', 'manual'), ] @@ -308,7 +308,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'MicroRTPS', u'MicroRTPS Documentation', + (master_doc, 'MicroXRCE-DDS', u'MicroXRCE-DDS Documentation', [author], 1) ] @@ -323,8 +323,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'MicroRTPS', u'MicroRTPS Documentation', - author, 'MicroRTPS', 'Documentation of eProsima MicroRTPS', + (master_doc, 'MicroXRCE-DDS', u'MicroXRCE-DDS Documentation', + author, 'MicroXRCE-DDS', 'Documentation of eProsima MicroXRCE-DDS', 'Miscellaneous'), ] diff --git a/docs/dependencies.rst b/docs/dependencies.rst index fc7eab66..4cbe9ca7 100644 --- a/docs/dependencies.rst +++ b/docs/dependencies.rst @@ -3,26 +3,26 @@ External dependencies Required dependences -------------------- -*Micro RTPS - Client* does not require external dependencies. +*Micro XRCE-DDS - Client* does not require external dependencies. -*Micro RTPS - Agent* requires following packages to work: +*Micro XRCE-DDS - Agent* requires following packages to work: -FastRTPS +Fast RTPS *eProsima Fast RTPS* could be installed following the instructions: `eProsima Fast RTPS installation guide `_. Windows ~~~~~~~ Microsoft Visual C++ 2013 or 2015 - *eProsima Micro RTPS* is supported on Windows over Microsoft Visual C++ 2013 or 2015 framework. + *eProsima Micro XRCE-DDS* is supported on Windows over Microsoft Visual C++ 2013 or 2015 framework. Additional Dependencies ----------------------- -The following dependences are not necessary to run Micro RTPS. +The following dependences are not necessary to run Micro XRCE-DDS. GTEST Gtest is the framework used to test the code through a complete set of tests. Java & Gradle - Java & Gradle is required to compile the code generation tool *Micro RTPS Gen*. + Java & Gradle is required to compile the code generation tool *Micro XRCE-DDS Gen*. diff --git a/docs/deployment.rst b/docs/deployment.rst index f995512f..61c2467c 100644 --- a/docs/deployment.rst +++ b/docs/deployment.rst @@ -3,7 +3,7 @@ Deployment example ================== -This part will show how to deploy a system using *Micro RTPS* in a real enviroment. +This part will show how to deploy a system using *Micro XRCE-DDS* in a real enviroment. An example of this can be found into ``examples/Deployment`` folder. Previous tutorials are based in `all in one` examples, that is, examples that create entities, publish or subscribe and then delete the resources. @@ -14,7 +14,7 @@ And other/s, that logs in the same session as the configure client (sharing the This way allows to create easy clients in production only with the purpose of send and receive data. Related to it, exists the concept of `profile` that allow to build the client library only with the behavior choosen (only publish or only suscribe, for example). -See :ref:`micro_rtps_client_label` for more information about this. +See :ref:`micro_xrce_dds_client_label` for more information about this. Next diagram shows an example about how to configure the enviroment using a `configurator client`. diff --git a/docs/entities.rst b/docs/entities.rst index bc92ce69..135490b6 100644 --- a/docs/entities.rst +++ b/docs/entities.rst @@ -3,9 +3,9 @@ Entities ======== -The protocol under *Micro RTPS* (XRCE), defines entities that have a direct correspondence with their analogous actor on *Fast RTPS* (DDS). -The entities manage the communication between *Micro RTPS Client* and the DDS Global Data Space. -Entities are stored in the *Micro RTPS Agent* and the *Micro RTPS Client* can create, use and destroy these entities. +The protocol under *Micro XRCE-DDS* (XRCE), defines entities that have a direct correspondence with their analogous actor on *Fast RTPS* (DDS). +The entities manage the communication between *Micro XRCE-DDS Client* and the DDS Global Data Space. +Entities are stored in the *Micro XRCE-DDS Agent* and the *Micro XRCE-DDS Client* can create, use and destroy these entities. The entities are uniquely identified by an ID called `Object ID`. `Object ID` is the way a *Client* refers to them inside an Agent. In most of the *Client* requests operations is necessary to specify an ID referring to one of the *Client* entities stored in the *Agent*. diff --git a/docs/gen.rst b/docs/gen.rst index 16c5e9fa..1ef69e57 100644 --- a/docs/gen.rst +++ b/docs/gen.rst @@ -1,9 +1,9 @@ -.. _micrortpsgen_label: +.. _microxrceddsgen_label: -Micro RTPS Gen -============== +Micro XRCE-DDS Gen +================== -*Micro RTPS Gen* is a Java application used to generate source code for the *eProsima Micro RTPS* software. +*Micro XRCE-DDS Gen* is a Java application used to generate source code for the *eProsima Micro XRCE-DDS* software. This tool is able to generate from a given IDL specification file, the C struct associated with the Topic, as well as, the serialization and deserialization methods. @@ -23,7 +23,7 @@ As an example of the powerful of this tool, the following shows the source code If we will perform the following command: :: - $ micrortpsgen ShapeType.idl + $ microxrceddsgen ShapeType.idl it will generate the following header file and its corresponding source: @@ -55,18 +55,18 @@ it will generate the following header file and its corresponding source: } ShapeType; - struct mcBuffer; + struct ucdrBuffer; - bool ShapeType_serialize_topic(struct mcBuffer* writer, const ShapeType* topic); - bool ShapeType_deserialize_topic(struct mcBuffer* reader, ShapeType* topic); + bool ShapeType_serialize_topic(struct ucdrBuffer* writer, const ShapeType* topic); + bool ShapeType_deserialize_topic(struct ucdrBuffer* reader, ShapeType* topic); uint32_t ShapeType_size_of_topic(const ShapeType* topic, uint32_t size); #endif // _ShapeType_H_ -*Micro RTPS Gen* is also able to generate both *publisher* and *subscriber* source code examples related with the topic speficified in the IDL file adding the flag ``-example``: :: +*Micro XRCE-DDS Gen* is also able to generate both *publisher* and *subscriber* source code examples related with the topic speficified in the IDL file adding the flag ``-example``: :: - $ micrortpsgen -example + $ microxrceddsgen -example In order to use these examples, the client library must be compiled with the ``WRITE_ACCESS_PROFILE`` option for the *publisher* @@ -75,7 +75,7 @@ and the ``READ_ACCESS_PROFILE`` option for the *subscriber*. Installation ------------ -For use *Micro RTPS Gen* you have to follow the next steps: +For use *Micro XRCE-DDS Gen* you have to follow the next steps: 1. Install its dependencies: @@ -85,8 +85,8 @@ For use *Micro RTPS Gen* you have to follow the next steps: 2. Clone the code from the GitHub repository. :: - $ git clone --recursive https://github.com/eProsima/micro-RTPS-gen.git - $ cd micro-RTPS-gen + $ git clone --recursive https://github.com/eProsima/micro-XRCE-DDS-gen.git + $ cd micro-XRCE-DDS-gen 3. Build the code with Gradle. :: @@ -95,5 +95,5 @@ For use *Micro RTPS Gen* you have to follow the next steps: Notes ----- -At the present time, *Micro RTPS Gen* only supports Structs composed of integer, string, array and sequence types -even though it is planned to enhance the capabilities of the *Micro RTPS Gen* tool in a near future. +At the present time, *Micro XRCE-DDS Gen* only supports Structs composed of integer, string, array and sequence types +even though it is planned to enhance the capabilities of the *Micro XRCE-DDS Gen* tool in a near future. diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 9a015b31..6841cf98 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -2,15 +2,15 @@ Getting started =============== -This page shows how to get started with the *Micro RTPS Client* development. +This page shows how to get started with the *Micro XRCE-DDS Client* development. We will create a *Client* that can publish and subscribe a topic. This tutorial has been extract from the examples found into ``examples/PublisherHelloWorld`` and ``examples/SubscriberHelloWorld``. First, we need to have on the system: - - :ref:`micro_rtps_client_label`. - - :ref:`micro_rtps_agent_label`. - - :ref:`micrortpsgen_label`. + - :ref:`micro_xrce_dds_client_label`. + - :ref:`micro_xrce_dds_agent_label`. + - :ref:`microxrceddsgen_label`. Generate from the IDL ^^^^^^^^^^^^^^^^^^^^^^ @@ -23,9 +23,9 @@ We will use HelloWorld as our Topic whose IDL is the following: :: }; In the *Client* we need to create an equivalent C type with its serialization/deserialization code. -This is done automatically by :ref:`micrortpsgen_label`: :: +This is done automatically by :ref:`microxrceddsgen_label`: :: - $ micrortpsgen HelloWorld.idl + $ microxrceddsgen HelloWorld.idl Initialize a Session ^^^^^^^^^^^^^^^^^^^^ @@ -37,15 +37,15 @@ Also, we will specify the max buffer for the streams and its historical associat #include "HelloWorldWriter.h" #define STREAM_HISTORY 8 - #define BUFFER_SIZE MR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY + #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY First, we need to create a Session indicating the transport to use. The agent must be configured for listening from udp at port 2018. .. code-block:: C - mrUDPTransport transport; - if(!mr_init_udp_transport(&transport, "127.0.0.1", 2018)) + uxrUDPTransport transport; + if(!uxr_init_udp_transport(&transport, "127.0.0.1", 2018)) { printf("Error at create transport.\n"); return 1; @@ -55,21 +55,21 @@ Next, we will a session that allow us interact with the agent: .. code-block:: C - mrSession session; - mr_init_session(&session, &transport.comm, 0xABCDABCD); - mr_set_topic_callback(&session, on_topic, NULL); - if(!mr_create_session(&session)) + uxrSession session; + uxr_init_session(&session, &transport.comm, 0xABCDABCD); + uxr_set_topic_callback(&session, on_topic, NULL); + if(!uxr_create_session(&session)) { printf("Error at create session.\n"); return 1; } -The first function ``mr_init_session`` initializes the ``Session`` structure with the transport and the `Client Key` (the session identifier for an agent). -The ``mr_set_topic_callback`` function is for registering the function ``on_topic`` which has been called when the `Client` receive a topic. -Once the session has been initialized, we can send the first message for login the client in agent side: ``mr_create_session``. +The first function ``uxr_init_session`` initializes the ``Session`` structure with the transport and the `Client Key` (the session identifier for an agent). +The ``uxr_set_topic_callback`` function is for registering the function ``on_topic`` which has been called when the `Client` receive a topic. +Once the session has been initialized, we can send the first message for login the client in agent side: ``uxr_create_session``. This function will try to connect with the agent by ``CONFIG_MAX_SESSION_CONNECTION_ATTEMPTS`` attempts (the value can be configurable at ``client.config``). -Optionally, we also could add a status callback with the function ``mr_set_status_callback``, but for the purpose of this example we do not need it. +Optionally, we also could add a status callback with the function ``uxr_set_status_callback``, but for the purpose of this example we do not need it. Once we have login the session successful, we can create the streams that we will use. In this case, we will use two, both reliables, for input and output. @@ -77,10 +77,10 @@ In this case, we will use two, both reliables, for input and output. .. code-block:: C uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; - mrStreamId reliable_out = mr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + uxrStreamId reliable_out = uxr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; - mrStreamId reliable_in = mr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + uxrStreamId reliable_in = uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); In order to publish and/or subscribe a topic, we need to create a hierarchy of XRCE entities in the agent side. These entities will be created from the client. @@ -94,9 +94,9 @@ We can do this calling *Create participant* operation: .. code-block:: C - mrObjectId participant_id = mr_object_id(0x01, MR_PARTICIPANT_ID); + uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); const char* participant_ref = "default participant"; - uint16_t participant_req = mr_write_create_participant_ref(&session, reliable_out, participant_id, participant_ref, MR_REPLACE); + uint16_t participant_req = uxr_write_create_participant_ref(&session, reliable_out, participant_id, participant_ref, UXR_REPLACE); In any XRCE Operation that creates an entity, an `Object ID` is necessary. It is used to represent and manage the entity in the *Client* side. @@ -112,9 +112,9 @@ Once the `Participant` has been created, we can use `Create topic` operation for .. code-block:: C - mrObjectId topic_id = mr_object_id(0x01, MR_TOPIC_ID); + uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = mr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, MR_REPLACE); + uint16_t topic_req = uxr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); As any other XRCE Operation used to create an entity, an Object ID must be specify to represent the entity. The ``participant_id`` is the participant where the Topic will be registered. @@ -128,13 +128,13 @@ We create a publisher or subscriber on a participant entity, so it is necessary .. code-block:: C - mrObjectId publisher_id = mr_object_id(0x01, MR_PUBLISHER_ID); + uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); const char* publisher_xml = ""; - uint16_t publisher_req = mr_write_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, MR_REPLACE); + uint16_t publisher_req = uxr_write_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); - mrObjectId subscriber_id = mr_object_id(0x01, MR_SUBSCRIBER_ID); + uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); const char* subscriber_xml = ""; - uint16_t subscriber_req = mr_write_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, MR_REPLACE); + uint16_t subscriber_req = uxr_write_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); DataWriters & DataReaders ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,13 +145,13 @@ The configuration about how these `DataReaders` and data writers works is contai .. code-block:: C - mrObjectId datawriter_id = mr_object_id(0x01, MR_DATAWRITER_ID); + uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); const char* datawriter_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datawriter_req = mr_write_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, MR_REPLACE); + uint16_t datawriter_req = uxr_write_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); - mrObjectId datareader_id = mr_object_id(0x01, MR_DATAREADER_ID); + uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datareader_req = mr_write_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, MR_REPLACE); + uint16_t datareader_req = uxr_write_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); Agent response ^^^^^^^^^^^^^^ @@ -165,24 +165,24 @@ The different status values that the agent can send to the client are the follow .. code-block:: C - MR_STATUS_OK - MR_STATUS_OK_MATCHED - MR_STATUS_ERR_DDS_ERROR - MR_STATUS_ERR_MISMATCH - MR_STATUS_ERR_ALREADY_EXISTS - MR_STATUS_ERR_DENIED - MR_STATUS_ERR_UNKNOWN_REFERENCE - MR_STATUS_ERR_INVALID_DATA - MR_STATUS_ERR_INCOMPATIBLE - MR_STATUS_ERR_RESOURCES + UXR_STATUS_OK + UXR_STATUS_OK_MATCHED + UXR_STATUS_ERR_DDS_ERROR + UXR_STATUS_ERR_MISMATCH + UXR_STATUS_ERR_ALREADY_EXISTS + UXR_STATUS_ERR_DENIED + UXR_STATUS_ERR_UNKNOWN_REFERENCE + UXR_STATUS_ERR_INVALID_DATA + UXR_STATUS_ERR_INCOMPATIBLE + UXR_STATUS_ERR_RESOURCES -The status can be handle by the ``on_status_callback`` callback (configured in ``mr_set_status_callback`` function) or by the ``run_session_until_all_status`` as we will see. +The status can be handle by the ``on_status_callback`` callback (configured in ``uxr_set_status_callback`` function) or by the ``run_session_until_all_status`` as we will see. .. code-block:: C uint8_t status[6]; // we have 6 request to check. uint16_t requests[6] = {participant_req, topic_req, publisher_req, subscriber_req, datawriter_req, datareader_req}; - if(!mr_run_session_until_all_status(&session, 1000, requests, status, 6)) + if(!uxr_run_session_until_all_status(&session, 1000, requests, status, 6)) { printf("Error at create entities\n"); return 1; @@ -191,13 +191,13 @@ The status can be handle by the ``on_status_callback`` callback (configured in ` The ``run_session`` functions are the main functions of the `Micro RTP Client` library. They performs serveral things: send the stream data to the agent, listen data from the agent, call callbacks, and manage the reliable connection. There are five variations of ``run_session`` function: -- ``mr_run_session_time`` -- ``mr_run_session_until_timeout`` -- ``mr_run_session_until_confirmed_delivery`` -- ``mr_run_session_until_all_status`` -- ``mr_run_session_until_one_status`` +- ``uxr_run_session_time`` +- ``uxr_run_session_until_timeout`` +- ``uxr_run_session_until_confirmed_delivery`` +- ``uxr_run_session_until_all_status`` +- ``uxr_run_session_until_one_status`` -Here we use the ``mr_run_session_until_all_status`` variation that will performs these actions until all status have been confirmed or the timeout has been reached. +Here we use the ``uxr_run_session_until_all_status`` variation that will performs these actions until all status have been confirmed or the timeout has been reached. This function will return ``true`` in case all status were `OK`. After call this function, the status can be read from the ``status`` array previously declared. @@ -210,23 +210,23 @@ For creating a message with data, first we must to decide which stream we want t HelloWorld topic = {count++, "Hello DDS world!"}; - mcBuffer mb; + ucdrBuffer mb; uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0); - (void) mr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); + (void) uxr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); (void) HelloWorld_serialize_topic(&mb, &topic); - mr_run_session_until_confirmed_delivery(&session, 1000); + uxr_run_session_until_confirmed_delivery(&session, 1000); -``HelloWorld_size_of_topic`` and ``HelloWorld_serialize_topic`` functions are automatically generated by :ref:`micrortpsgen_label` from the IDL. -The function ``mr_prepare_output_stream`` requests a writing for a topic of ``topic_size`` size into the reliable stream represented by ``reliable_out``, +``HelloWorld_size_of_topic`` and ``HelloWorld_serialize_topic`` functions are automatically generated by :ref:`microxrceddsgen_label` from the IDL. +The function ``uxr_prepare_output_stream`` requests a writing for a topic of ``topic_size`` size into the reliable stream represented by ``reliable_out``, with a ``datawriter_id`` (correspond to the data writer entity used for sending the data in the `DDS World`). -If the stream is available and the topic fits in it, the function will initialize the ``mcBuffer`` structure ``mb``. -Once the ``mcBuffer`` is prepared, the topic can be serialized into it. -We are careless about ``mr_prepare_output_stream`` return value because the serialization only will occur if the ``mcBuffer` is valid`` +If the stream is available and the topic fits in it, the function will initialize the ``ucdrBuffer`` structure ``mb``. +Once the ``ucdrBuffer`` is prepared, the topic can be serialized into it. +We are careless about ``uxr_prepare_output_stream`` return value because the serialization only will occur if the ``ucdrBuffer` is valid`` After the write function, as happend with the creation of entities, the topic has been serialized into the buffer but it has not been sent yet. To send the topic is necessary call to a ``run_session`` function. -In this case, we call to ``mr_run_session_until_confirmed_delivery`` that will wait until the message was confirmed or until the timeout has been reached. +In this case, we call to ``uxr_run_session_until_confirmed_delivery`` that will wait until the message was confirmed or until the timeout has been reached. Read Data ^^^^^^^^^ @@ -236,10 +236,10 @@ Current implementation sends one topic to the client for each read data operatio .. code-block:: C - mrDeliveryControl delivery_control = {0}; - delivery_control.max_samples = MR_MAX_SAMPLES_UNLIMITED; + uxrDeliveryControl delivery_control = {0}; + delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED; - uint16_t read_data_req = mr_write_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); + uint16_t read_data_req = uxr_write_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); In order to configure how the agent will send the topic, we must set the input stream. In this case, we use the input reliable stream previously defined. ``datareader_id`` corresponds with the `DataDeader` entity used for receiving the data. @@ -250,7 +250,7 @@ The ``run_session`` function will call the topic callback each time a topic will .. code-block:: C - void on_topic(mrSession* session, mrObjectId object_id, uint16_t request_id, mrStreamId stream_id, struct mcBuffer* mb, void* args) + void on_topic(uxrSession* session, uxrObjectId object_id, uint16_t request_id, uxrStreamId stream_id, struct ucdrBuffer* mb, void* args) { (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) args; @@ -270,11 +270,11 @@ This is done sending the next message: .. code-block:: C - mr_delete_session(&session); + uxr_delete_session(&session); After this, we can close the transport used by the session. .. code-block:: C - mr_close_udp_transport(&transport); + uxr_close_udp_transport(&transport); diff --git a/docs/images/architecture.png b/docs/images/architecture.png deleted file mode 100644 index 80ba9f86485bc6f139214a7049c71974f491de28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22721 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 XnOJY@%S%szClKtqg;C+P+hP9&q~d?C diff --git a/docs/images/architecture.svg b/docs/images/architecture.svg deleted file mode 100644 index a42da1f6..00000000 --- a/docs/images/architecture.svg +++ /dev/null @@ -1,2 +0,0 @@ - -
Low resources Device
Low resources Device<br>
Micro RTPS Agent
[Not supported by viewer]
Micro RTPS Client
[Not supported by viewer]
Low resources Device
Low resources Device<br>
Micro RTPS Client
[Not supported by viewer]
DDS-XRCE
DDS-XRCE
DDS-XRCE
DDS-XRCE<br>
RTPS/DDS
RTPS/DDS
\ No newline at end of file diff --git a/docs/images/entities_hierarchy.svg b/docs/images/entities_hierarchy.svg index 52482a18..e099c973 100644 --- a/docs/images/entities_hierarchy.svg +++ b/docs/images/entities_hierarchy.svg @@ -1,2 +1,2 @@ -
Micro RTPS Agent
[Not supported by viewer]
Micro RTPS Client
Micro RTPS Client
Participant
Participant
1
1
Publisher
Publisher
*
[Not supported by viewer]
Data Writer
Data Writer
Subscriber
Subscriber
Data Reader
Data Reader
1
1
*
[Not supported by viewer]
1
1
*
[Not supported by viewer]
*
[Not supported by viewer]
1
1
1
1
*
[Not supported by viewer]
*
[Not supported by viewer]
RTPS-MESSAGES
RTPS-MESSAGES
\ No newline at end of file +
Micro XRCE-DDS Agent
<div align="center">Micro XRCE-DDS Agent<br></div>
ProxyClient
ProxyClient
Participant
Participant
1
1
Publisher
Publisher
DataWriter
DataWriter
Subscriber
Subscriber
DataReader
DataReader
*
[Not supported by viewer]
*
[Not supported by viewer]
*
[Not supported by viewer]
*
[Not supported by viewer]
1
1
1
1
1
1
1
1
*
[Not supported by viewer]
*
[Not supported by viewer]
*
[Not supported by viewer]
1
1
1
1
1
1
1
1
Topic
Topic
\ No newline at end of file diff --git a/docs/images/xrcedds_architecture.svg b/docs/images/xrcedds_architecture.svg new file mode 100644 index 00000000..9109aacc --- /dev/null +++ b/docs/images/xrcedds_architecture.svg @@ -0,0 +1,2 @@ + +
Micro XRCE-DDS Agent
[Not supported by viewer]
XRCE-DDS
[Not supported by viewer]
RTPS
RTPS
Low Resources Device
Low Resources Device
Micro XRCE-DDS Client
<b>Micro XRCE-DDS Client</b>
XRCE-DDS
[Not supported by viewer]
Low Resources Device
Low Resources Device
Micro XRCE-DDS Client
<b>Micro XRCE-DDS Client</b>
\ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 345f8c6c..fe81f56a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,29 +1,29 @@ -.. eProsima Micro RTPS documentation master file. +.. eProsima Micro XRCE-DDS documentation master file. -.. _micrortps_doc: +.. _microxrcedds_doc: -eProsima Micro RTPS -------------------- +eProsima Micro XRCE-DDS +----------------------- -*eProsima Micro RTPS* is a software solution which allows to communicate eXtremely Resource Constrained Environments (XRCEs) with an existing DDS network. +*eProsima Micro XRCE-DDS* is a software solution which allows to communicate eXtremely Resource Constrained Environments (XRCEs) with an existing DDS network. This implementation complies with the specification proposal, "eXtremely Resource Constrained Environments DDS (DDS-XRCE)" submitted to the Object Management Group (OMG) consortium. -*Micro RTPS* implements a client-server protocol to enable resource-constrained devices (clients) to take part in DDS communications. -*Micro RTPS Agent* (server) makes possible this communication. -The *Micro RTPS Agent* acts on behalf of the *Micro RTPS Clients* and enables them to take part as DDS publishers and/or subscribers in the DDS Global Data Space. +*Micro XRCE-DDS* implements a client-server protocol to enable resource-constrained devices (clients) to take part in DDS communications. +*Micro XRCE-DDS Agent* (server) makes possible this communication. +The *Micro XRCE-DDS Agent* acts on behalf of the *Micro XRCE-DDS Clients* and enables them to take part as DDS publishers and/or subscribers in the DDS Global Data Space. -*Micro RTPS* provides both, a plug and play *Micro RTPS Agent* and an API layer which allows you to implement your *Micro RTPS Clients*. +*Micro XRCE-DDS* provides both, a plug and play *Micro XRCE-DDS Agent* and an API layer which allows you to implement your *Micro XRCE-DDS Clients*. -.. image:: images/architecture.svg +.. image:: images/xrcedds_architecture.svg Installation ~~~~~~~~~~~~ -To install *Micro RTPS*, follow the instructions of :ref:`installation_label` page. +To install *Micro XRCE-DDS*, follow the instructions of :ref:`installation_label` page. User manual ~~~~~~~~~~~ -To test *Micro RTPS* in your computer, you can follow the :ref:`quickstart_label` instructions. +To test *Micro XRCE-DDS* in your computer, you can follow the :ref:`quickstart_label` instructions. This page shows how to create a simple publisher as a XRCE client that send topics into the DDS World. Additionally, there is an interactive example called :ref:`shapes_demo_label` that allow you to create entities and @@ -31,15 +31,15 @@ to send/receive topics by the instructions given by command line. This example is useful to understand how XRCE protocol works along to the DDS World. To create your own client, you can follow the the instructions of :ref:`getting_started_label` page. -This is a tutorial that describe briefly how *Micro RTPS* API is and how it works. +This is a tutorial that describe briefly how *Micro XRCE-DDS* API is and how it works. -To know more about *Micro RTPS*, you can read the corresponding parts to the :ref:`micro_rtps_client_label` or the :ref:`micro_rtps_agent_label`. +To know more about *Micro XRCE-DDS*, you can read the corresponding parts to the :ref:`micro_xrce_dds_client_label` or the :ref:`micro_xrce_dds_agent_label`. If you are interesting in how XRCE works, read :ref:`entities_label` and :ref:`operations_label` pages. -Micro RTPS Gen -~~~~~~~~~~~~~~ -To create a serialization/deserialization topic code for *Micro RTPS Client* and make easy the built of examples using thoses topics, there is a tool called `micrortpsgen`. -Information about this tool can be found in :ref:`micrortpsgen_label` page. +Micro XRCE-DDS Gen +~~~~~~~~~~~~~~~~~~ +To create a serialization/deserialization topic code for *Micro XRCE-DDS Client* and make easy the built of examples using thoses topics, there is a tool called `microxrceddsgen`. +Information about this tool can be found in :ref:`microxrceddsgen_label` page. Index ----- diff --git a/docs/installation.rst b/docs/installation.rst index 2a053b6d..e628796e 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -9,8 +9,8 @@ Installing Agent and Client Clone the project from GitHub: :: - $ git clone --recursive https://github.com/eProsima/micro-RTPS.git - $ cd micro-RTPS + $ git clone --recursive https://github.com/eProsima/micro-XRCE-DDS.git + $ cd micro-XRCE-DDS $ mkdir build && cd build On Linux, inside of ``build`` folder, execute the following commands: :: @@ -24,15 +24,15 @@ On Windows choose the Visual Studio version using the CMake option *-G*, for exa $ cmake -G "Visual Studio 14 2015 Win64" -DTHIRDPARTY=ON .. $ cmake --build . --target install -Now you have *Micro RTPS Agent* and *Micro RTPS Client* installed in your system. +Now you have *Micro XRCE-DDS Agent* and *Micro XRCE-DDS Client* installed in your system. Installing the Agent stand-alone -------------------------------- Clone the project from GitHub: :: - $ git clone https://github.com/eProsima/micro-RTPS-agent.git - $ cd micro-RTPS-agent + $ git clone https://github.com/eProsima/micro-XRCE-DDS-agent.git + $ cd micro-XRCE-DDS-agent $ mkdir build && cd build On Linux, inside of ``build`` folder, execute the following commands: :: @@ -46,7 +46,7 @@ On Windows first select the Visual Studio version: :: $ cmake -G "Visual Studio 14 2015 Win64" -DTHIRDPARTY=ON .. $ cmake --build . --target install -Now you have the executable `Micro RTPS Agent` installed in your system. Before running it, you need to add ``/usr/local/lib`` to the dynamic loader-linker directories. :: +Now you have the executable `Micro XRCE-DDS Agent` installed in your system. Before running it, you need to add ``/usr/local/lib`` to the dynamic loader-linker directories. :: sudo ldconfig /usr/local/lib/ @@ -55,8 +55,8 @@ Installing the Client stand-alone Clone the project from GitHub: :: - $ git clone https://github.com/eProsima/micro-RTPS-client.git - $ cd micro-RTPS-client + $ git clone https://github.com/eProsima/micro-XRCE-DDS-client.git + $ cd micro-XRCE-DDS-client $ mkdir build && cd build On Linux, inside of ``build`` folder, execute the following commands: :: @@ -70,14 +70,14 @@ On Windows first select the Visual Studio version: :: $ cmake -G "Visual Studio 14 2015 Win64" -DTHIRDPARTY=ON .. $ cmake --build . --target install -If you want to install the *Micro RTPS Client* examples you can add ``-DEPROSIMA_BUILD_EXAMPLES=ON`` to the CMake command line options. +If you want to install the *Micro XRCE-DDS Client* examples you can add ``-DEPROSIMA_BUILD_EXAMPLES=ON`` to the CMake command line options. This flag will enable the compilation of the examples when the project it is compiled. There are several CMake definitions for configuring the build of the client library at compile time. -You can found them in :ref:`micro_rtps_client_label` page under `Configuration` section. +You can found them in :ref:`micro_xrce_dds_client_label` page under `Configuration` section. Compiling an app with the Client library ---------------------------------------- For building your client program you need to build against the following libs: :: - gcc -lmicrocdr -lmicrortps_client + gcc -lmicrocdr -lmicroxrcedds_client diff --git a/docs/introduction.rst b/docs/introduction.rst index 4c6a0aeb..769c0492 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -6,7 +6,7 @@ Introduction DDS-XRCE protocol ----------------- -`Micro RTPS` implements `DDS-XRCE protocol `_ +`Micro XRCE-DDS` implements `DDS-XRCE protocol `_ specified in the `DDS for eXtremely Resource Constrained Environments` proposal submitted to the `Object Management Group (OMG)` consortium. This protocol allows to communicate resource constrained clients with a larger `DDS (Data Distribution Service)` network. This communication is done using a client-server architecture, @@ -18,28 +18,28 @@ XRCE Clients ask the XRCE Agents to run operations and the XRCE Agents reply wit Making use of those operations, XRCE Clients are able to create the DDS entities hierarchy necessary to publish and/or receive data from DDS. DDS entities are created and stored on the XRCE Agent side so the XRCE Clients can reuse them at will. -`Micro RTPS` implements the DDS-XRCE protocol using a *Micro RTPS Agent* as server and providing a C API for developing XRCE Clients. -`Micro RTPS Agent` uses `Fast RTPS` to reach the DDS Global Data Space. +`Micro XRCE-DDS` implements the DDS-XRCE protocol using a *Micro XRCE-DDS Agent* as server and providing a C API for developing XRCE Clients. +`Micro XRCE-DDS Agent` uses `Fast RTPS` to reach the DDS Global Data Space. -.. image:: images/architecture.svg +.. image:: images/xrcedds_architecture.svg Fast RTPS ````````` -*eProsima Fast RTPS* is a C++ implementation of the `RTPS (Real-Time Publish-Subscribe)` protocol, +*eProsima Fast RTPS* is a C++ implementation of the `XRCE-DDS (Real-Time Publish-Subscribe)` protocol, which provides publisher-subscriber communications over unreliable transports such as UDP, as defined and maintained by the `OMG` consortium. -RTPS is also the wire interoperability protocol defined for the `DDS` standard, again by the `OMG`. +XRCE-DDS is also the wire interoperability protocol defined for the `DDS` standard, again by the `OMG`. For deeper information please refer to the official documentation: `eProsima Fast RTPS `_ Operations and entities ----------------------- -*Micro RTPS* communication between XRCE Client and XRCE Agent is based upon :ref:`operations_label` and responses. +*Micro XRCE-DDS* communication between XRCE Client and XRCE Agent is based upon :ref:`operations_label` and responses. Clients request operations to the Agent. The Agent will process the received operations and generate responses with the result of these operations. Clients may process the responses to know how an operations request has ended in the Agent. -*Micro RTPS Client* can request a variety of operations to the *Micro RTPS Agent*: +*Micro XRCE-DDS Client* can request a variety of operations to the *Micro XRCE-DDS Agent*: * Create and delete sessions. * Create and delete entities. @@ -74,6 +74,6 @@ Topic Type ---------- The data sent by the `Client` to the `DDS Global Data Space` uses the same principles as in `Fast RTPS`. The `Interface Definition Language (IDL) `_ is used to define the type and must be known by the client. -Having the type defined as `IDL` we provide the :ref:`micrortpsgen_label` tool. -This tool is able to generate a compatible type that the *Micro RTPS Client* can use to send and receive. +Having the type defined as `IDL` we provide the :ref:`microxrceddsgen_label` tool. +This tool is able to generate a compatible type that the *Micro XRCE-DDS Client* can use to send and receive. The type should match the one used on the DDS Side. diff --git a/docs/operations.rst b/docs/operations.rst index f9e02732..8e898bde 100644 --- a/docs/operations.rst +++ b/docs/operations.rst @@ -2,9 +2,9 @@ Operations ========== -Operations are the possible actions your *Micro RTPS Client* can ask to the *Micro RTPS Agent*. +Operations are the possible actions your *Micro XRCE-DDS Client* can ask to the *Micro XRCE-DDS Agent*. Operations revolve around `entities`. :ref:`entities_label`. -*Micro RTPS Agent* will respond to all the requests with the status of the operation. +*Micro XRCE-DDS Agent* will respond to all the requests with the status of the operation. Types ----- @@ -38,4 +38,4 @@ Creating a Topic, a DataWriter or a DataReader needs to be done using DDS XML co That XML configuration follows the same rules as in *Fast RTPS*. Creating a Participant is done using the ``default participant`` profile found already preconfigured in the agent. -Yo can change the Participant configuration changing the "DEFAULT_FASTRTPS_PROFILES.xml" file found along with de *Micro RTPS Agent* installation. +Yo can change the Participant configuration changing the ``DEFAULT_FASTRTPS_PROFILES.xml`` file found along with de *Micro XRCE-DDS Agent* installation. diff --git a/docs/quickstart.rst b/docs/quickstart.rst index eb2d18b4..83752894 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -2,8 +2,8 @@ Quick start =========== -`Micro RTPS` provides a C API which allows the creation of `Micro RTPS Clients` that publish and/or subscribe to topics from DDS Global Data Space. -The following example shows how to create a simple `Micro RTPS Client` and `Micro RTPS Agent` for publishing and subscribing to the DDS world, using this HelloWorld.idl: :: +`Micro XRCE-DDS` provides a C API which allows the creation of `Micro XRCE-DDS Clients` that publish and/or subscribe to topics from DDS Global Data Space. +The following example shows how to create a simple `Micro XRCE-DDS Client` and `Micro XRCE-DDS Agent` for publishing and subscribing to the DDS world, using this HelloWorld.idl: :: struct HelloWorld { @@ -13,7 +13,7 @@ The following example shows how to create a simple `Micro RTPS Client` and `Micr First of all, we launch the `Agent`. For this example, the `Client` - `Agent` communication will be done through UDP: :: - $ cd /usr/local/bin && MicroRTPSAgent udp 2018 + $ cd /usr/local/bin && MicroXRCE-DDSAgent udp 2018 Along with the `Agent`, the `PublishHelloWorldClient` example provided in the source code is launched. This `Client` example will publish in the DDS World the HelloWorld topic. :: @@ -26,13 +26,13 @@ The code of the *PublishHelloWorldClient* is the following: #include "HelloWorldWriter.h" - #include + #include #include #include //strcmp #include //atoi #define STREAM_HISTORY 8 - #define BUFFER_SIZE MR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY + #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY int main(int args, char** argv) { @@ -45,17 +45,17 @@ The code of the *PublishHelloWorldClient* is the following: uint32_t max_topics = (args == 2) ? (uint32_t)atoi(argv[1]) : UINT32_MAX; // Transport - mrUDPTransport transport; - if(!mr_init_udp_transport(&transport, "127.0.0.1", 2018)) + uxrUDPTransport transport; + if(!uxr_init_udp_transport(&transport, "127.0.0.1", 2018)) { printf("Error at create transport.\n"); return 1; } // Session - mrSession session; - mr_init_session(&session, &transport.comm, 0xAAAABBBB); - if(!mr_create_session(&session)) + uxrSession session; + uxr_init_session(&session, &transport.comm, 0xAAAABBBB); + if(!uxr_create_session(&session)) { printf("Error at create session.\n"); return 1; @@ -63,32 +63,32 @@ The code of the *PublishHelloWorldClient* is the following: // Streams uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; - mrStreamId reliable_out = mr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + uxrStreamId reliable_out = uxr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; - mr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); // Create entities - mrObjectId participant_id = mr_object_id(0x01, MR_PARTICIPANT_ID); + uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); const char* participant_ref = "default participant"; - uint16_t participant_req = mr_write_create_participant_ref(&session, reliable_out, participant_id, participant_ref, MR_REPLACE); + uint16_t participant_req = uxr_write_create_participant_ref(&session, reliable_out, participant_id, participant_ref, UXR_REPLACE); - mrObjectId topic_id = mr_object_id(0x01, MR_TOPIC_ID); + uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = mr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, MR_REPLACE); + uint16_t topic_req = uxr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); - mrObjectId publisher_id = mr_object_id(0x01, MR_PUBLISHER_ID); + uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); const char* publisher_xml = ""; - uint16_t publisher_req = mr_write_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, MR_REPLACE); + uint16_t publisher_req = uxr_write_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); - mrObjectId datawriter_id = mr_object_id(0x01, MR_DATAWRITER_ID); + uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); const char* datawriter_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datawriter_req = mr_write_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, MR_REPLACE); + uint16_t datawriter_req = uxr_write_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); // Send create entities message and wait its status uint8_t status[4]; uint16_t requests[4] = {participant_req, topic_req, publisher_req, datawriter_req}; - if(!mr_run_session_until_all_status(&session, 1000, requests, status, 4)) + if(!uxr_run_session_until_all_status(&session, 1000, requests, status, 4)) { printf("Error at create entities: participant: %i topic: %i publisher: %i darawriter: %i\n", status[0], status[1], status[2], status[3]); return 1; @@ -101,12 +101,12 @@ The code of the *PublishHelloWorldClient* is the following: { HelloWorld topic = {count++, "Hello DDS world!"}; - mcBuffer mb; + ucdrBuffer mb; uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0); - mr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); + uxr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); HelloWorld_serialize_topic(&mb, &topic); - connected = mr_run_session_until_time(&session, 1000); + connected = uxr_run_session_until_time(&session, 1000); if(connected) { printf("Sent topic: %s, id: %i\n", topic.message, topic.index); @@ -114,8 +114,8 @@ The code of the *PublishHelloWorldClient* is the following: } // Delete resources - mr_delete_session(&session); - mr_close_udp_transport(&transport); + uxr_delete_session(&session); + uxr_close_udp_transport(&transport); return 0; } @@ -130,15 +130,15 @@ The code of the *SubscriberHelloWorldClient* is the following: #include "HelloWorld.h" - #include + #include #include //strcmp #include //atoi #include #define STREAM_HISTORY 8 - #define BUFFER_SIZE MR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY + #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY - void on_topic(mrSession* session, mrObjectId object_id, uint16_t request_id, mrStreamId stream_id, struct mcBuffer* mb, void* args) + void on_topic(uxrSession* session, uxrObjectId object_id, uint16_t request_id, uxrStreamId stream_id, struct ucdrBuffer* mb, void* args) { (void) session; (void) object_id; (void) request_id; (void) stream_id; @@ -163,18 +163,18 @@ The code of the *SubscriberHelloWorldClient* is the following: uint32_t max_topics = (args == 2) ? (uint32_t)atoi(argv[1]) : UINT32_MAX; // Transport - mrUDPTransport transport; - if(!mr_init_udp_transport(&transport, "127.0.0.1", 2018)) + uxrUDPTransport transport; + if(!uxr_init_udp_transport(&transport, "127.0.0.1", 2018)) { printf("Error at create transport.\n"); return 1; } // Session - mrSession session; - mr_init_session(&session, &transport.comm, 0xCCCCDDDD); - mr_set_topic_callback(&session, on_topic, &count); - if(!mr_create_session(&session)) + uxrSession session; + uxr_init_session(&session, &transport.comm, 0xCCCCDDDD); + uxr_set_topic_callback(&session, on_topic, &count); + if(!uxr_create_session(&session)) { printf("Error at create session.\n"); return 1; @@ -182,53 +182,53 @@ The code of the *SubscriberHelloWorldClient* is the following: // Streams uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; - mrStreamId reliable_out = mr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + uxrStreamId reliable_out = uxr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; - mrStreamId reliable_in = mr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + uxrStreamId reliable_in = uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); // Create entities - mrObjectId participant_id = mr_object_id(0x01, MR_PARTICIPANT_ID); + uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); const char* participant_ref = "default participant"; - uint16_t participant_req = mr_write_create_participant_ref(&session, reliable_out, participant_id, 0, participant_ref, MR_REPLACE); + uint16_t participant_req = uxr_write_create_participant_ref(&session, reliable_out, participant_id, 0, participant_ref, UXR_REPLACE); - mrObjectId topic_id = mr_object_id(0x01, MR_TOPIC_ID); + uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = mr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, MR_REPLACE); + uint16_t topic_req = uxr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); - mrObjectId subscriber_id = mr_object_id(0x01, MR_SUBSCRIBER_ID); + uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); const char* subscriber_xml = ""; - uint16_t subscriber_req = mr_write_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, MR_REPLACE); + uint16_t subscriber_req = uxr_write_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); - mrObjectId datareader_id = mr_object_id(0x01, MR_DATAREADER_ID); + uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datareader_req = mr_write_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, MR_REPLACE); + uint16_t datareader_req = uxr_write_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); // Send create entities message and wait its status uint8_t status[4]; uint16_t requests[4] = {participant_req, topic_req, subscriber_req, datareader_req}; - if(!mr_run_session_until_all_status(&session, 1000, requests, status, 4)) + if(!uxr_run_session_until_all_status(&session, 1000, requests, status, 4)) { printf("Error at create entities: participant: %i topic: %i subscriber: %i datareader: %i\n", status[0], status[1], status[2], status[3]); return 1; } // Request topics - mrDeliveryControl delivery_control = {0}; - delivery_control.max_samples = MR_MAX_SAMPLES_UNLIMITED; - uint16_t read_data_req = mr_write_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); + uxrDeliveryControl delivery_control = {0}; + delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED; + uint16_t read_data_req = uxr_write_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); // Read topics bool connected = true; while(connected && count < max_topics) { uint8_t read_data_status; - connected = mr_run_session_until_all_status(&session, MR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); + connected = uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); } // Delete resources - mr_delete_session(&session); - mr_close_udp_transport(&transport); + uxr_delete_session(&session); + uxr_close_udp_transport(&transport); return 0; } @@ -246,11 +246,11 @@ In order to see the messages from the DDS Global Data Space point of view, you c Learn More ---------- -To learn more about DDS and FastRTPS: `eProsima Fast RTPS `_ +To learn more about DDS and Fast RTPS: `eProsima Fast RTPS `_ -To learn how to install *Micro RTPS* read: :ref:`installation_label` +To learn how to install *Micro XRCE-DDS* read: :ref:`installation_label` -To learn more about *Micro RTPS* read :ref:`user` +To learn more about *Micro XRCE-DDS* read :ref:`user` -To learn more about *Micro RTPS Gen* read: :ref:`micrortpsgen_label` +To learn more about *Micro XRCE-DDS Gen* read: :ref:`microxrceddsgen_label` diff --git a/docs/shapes_demo.rst b/docs/shapes_demo.rst index 902984b4..5e02883d 100644 --- a/docs/shapes_demo.rst +++ b/docs/shapes_demo.rst @@ -4,7 +4,7 @@ Shapes Demo =========== `ShapesDemo `_ is an interactive example for testing how `Fast RTPS` working in the `DDS Global Data Space`. -Because the aim of `Micro RTPS` is connect a `XRCE Client` to the `DDS World`, in this example we will create a client which will interact with the `Shapes Demo`. +Because the aim of `Micro XRCE-DDS` is connect a `XRCE Client` to the `DDS World`, in this example we will create a client which will interact with the `Shapes Demo`. This interactive client waits for user input indicating commands to execute. The available commands are the following: From daa676fde4e918a2177df661012d607502d586c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Mon, 15 Oct 2018 07:31:00 +0200 Subject: [PATCH 08/16] Refs #3447. Updated with discovery API doc. (#7) --- docs/client.rst | 68 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index ba258afd..36c89751 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -51,6 +51,9 @@ For incorporating the changes to your project, is necessary to run the ``cmake`` ``PROFILE_WRITE_ACCESS=`` Enables or disables the functions related to write topics. +``PROFILE_DISCOVERY=`` + Enables or disables the functions the discovery feature. + ``PROFILE_UDP_TRANSPORT=`` Enables or disables the posibility to connect with the agent by UDP. @@ -380,7 +383,7 @@ The function will return ``true`` if one status have been received and has the v Create entities by XML profile `````````````````````````````` These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` is enabled in the ``client.config`` file. -The declaration of these function can be found in ``uxr/client/profile/session/create_entities_xml.h``. +The declaration of these functions can be found in ``uxr/client/profile/session/create_entities_xml.h``. ------ @@ -501,7 +504,7 @@ Create a `datareader` entity in the agent. Create entities by reference profile ```````````````````````````````````` These functions are enabled when ``PROFILE_CREATE_ENTITIES_REF`` is enabled in the ``client.config`` file. -The declaration of these function can be found in ``uxr/client/profile/session/create_entities_ref.h``. +The declaration of these functions can be found in ``uxr/client/profile/session/create_entities_ref.h``. ------ @@ -527,7 +530,7 @@ Create a `datareader` entity in the agent. Create entities common profile `````````````````````````````` These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` or ``PROFILE_CREATE_ENTITIES_REF`` are enabled in the ``client.config`` file. -The declaration of these function can be found in ``uxr/client/profile/session/common_create_entities.h``. +The declaration of these functions can be found in ``uxr/client/profile/session/common_create_entities.h``. ------ @@ -546,7 +549,7 @@ Removes a entity. Read access profile ``````````````````` These functions are enabled when PROFILE_READ_ACCESS is enabled in the ``client.config`` file. -The declaration of these function can be found in ``uxr/client/profile/session/read_access.h``. +The declaration of these functions can be found in ``uxr/client/profile/session/read_access.h``. ------ @@ -573,7 +576,7 @@ If there is an error, a status error will be sent by the agent. Write access profile ```````````````````` These functions are enabled when PROFILE_WRITE_ACCESS is enabled in the ``client.config`` file. -The declaration of these function can be found in ``uxr/client/profile/session/write_access.h``. +The declaration of these functions can be found in ``uxr/client/profile/session/write_access.h``. ------ @@ -599,6 +602,61 @@ NOTE: All `topic_size` bytes requested will be sent to the agent after a ``run_s ------ +Discovery profile +``````````````````` +The discovery profile allows to discover agents in the network by UDP. +The reachable agents will respond to the discovery call sending information about them, as their ip and port. +There is two modes: multicast and unicast. +The discovery phase can be performed before the `uxr_create_session` call in order to determine the agent to connect with. +These functions are enabled when PROFILE_DISCOVERY is enabled in the ``client.config`` file. +The declaration of these functions can be found in ``uxr/client/profile/discovery/discovery.h``. + +bool uxr_discovery_agents_multicast(uint32_t attemps, int period, uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* choosen); + +------ + +.. code-block:: c + + bool uxr_discovery_agents_multicast(uint32_t attempts, int period, + uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* choosen); + +Searches into the network using multicast ip "239.255.0.2" and port 7400 (default used by the agent) in order to discover agents. + +:attempts: The number of attempts to send the discovery message to the network. +:period: How often will be sent the discovery message to the network. +:on_agent_func: The callback function that will be called when an agent was discovered. + The callback returns a boolean value. + A `true` means that the discovery rutine will be end and exit. + The current agent will be selected as *choosen*. + A `false` implies that the discovery rutine must to continue searching agents. +:args: User arguments passed to the callback function. +:choosen: If the callback function was returned `true`, this value will contains the agent value of the callback. + +------ + +.. code-block:: c + + bool uxr_discovery_agents_unicast(uint32_t attempts, int period, + uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* choosen, + const uxrAgentAddress* agent_list, size_t agent_list_size); + +Searches into the network using a list of unicast directions in order to discover agents. + +:attempts: The number of attempts to send the discovery message to the network. +:period: How often will be sent the discovery message to the network. +:on_agent_func: The callback function that will be called when an agent was discovered. + The callback returns a boolean value. + A ``true`` means that the discovery rutine will be end and exit. + The current agent will be selected as *choosen*. + A ``false`` implies that the discovery rutine must to continue searching agents. +:args: User arguments passed to the callback function. +:choosen: If the callback function was returned ``true``, this value will contains the agent value of the callback. +:agent_list: The list of address where discover agent. + By default the agents will be listen at **port 7400** the discovery messages.. +:agent_list_size: The size of the ``agent_list``. + +------ + Topic serialization ``````````````````` Functions to serialize and deserialize topics. From be2ebf296edf8cb0fd892cc4a87cd87284adc5e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Tue, 16 Oct 2018 06:57:00 +0200 Subject: [PATCH 09/16] Modified function names write -> buffer (#8) * Modified function names write -> buffer * Increase uxr_buffer_ functions documentation. --- docs/client.rst | 40 +++++++++++++++++++++++++++++----------- docs/getting_started.rst | 14 +++++++------- docs/quickstart.rst | 18 +++++++++--------- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index 36c89751..d39e4857 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -389,9 +389,11 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ .. code-block:: c - uint16_t uxr_write_configure_participant_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uint16_t domain, const char* xml, uint8_t mode); + uint16_t uxr_buffer_configure_participant_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uint16_t domain, const char* xml, uint8_t mode); -Create a `participant` entity in the agent. +Creates a `participant` entity in the agent. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. @@ -408,9 +410,11 @@ Create a `participant` entity in the agent. .. code-block:: c - uint16_t uxr_write_configure_topic_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_configure_topic_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); -Create a `topic` entity in the agent. +Creates a `topic` entity in the agent. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. @@ -427,9 +431,11 @@ Create a `topic` entity in the agent. .. code-block:: c - uint16_t uxr_write_configure_publisher_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_configure_publisher_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); Create a `publisher` entity in the agent. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. @@ -446,9 +452,11 @@ Create a `publisher` entity in the agent. .. code-block:: c - uint16_t uxr_write_configure_subscriber_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_configure_subscriber_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); Create a `publisher` entity in the agent. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. @@ -465,9 +473,11 @@ Create a `publisher` entity in the agent. .. code-block:: c - uint16_t uxr_write_configure_datawriter_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId publisher_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_configure_datawriter_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId publisher_id, const char* xml, uint8_t mode); Create a `datawriter_id` entity in the agent. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. @@ -484,9 +494,11 @@ Create a `datawriter_id` entity in the agent. .. code-block:: c - uint16_t uxr_write_configure_datareader_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId subscriber_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_configure_datareader_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId subscriber_id, const char* xml, uint8_t mode); Create a `datareader` entity in the agent. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. @@ -510,9 +522,11 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ .. code-block:: c - uint16_t uxr_write_create_participant_ref(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, const char* ref, uint8_t mode); + uint16_t uxr_buffer_create_participant_ref(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, const char* ref, uint8_t mode); Create a `datareader` entity in the agent. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. @@ -536,9 +550,11 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ .. code-block:: c - uint16_t uxr_write_delete_entity(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id); + uint16_t uxr_buffer_delete_entity(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id); Removes a entity. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. @@ -555,7 +571,7 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ .. code-block:: c - uint16_t uxr_write_request_data(uxrSession* session, uxrStreamId stream_id, uxrObjectId datareader_id, uxrStreamId data_stream_id, uxrDeliveryControl* delivery_control); + uint16_t uxr_buffer_request_data(uxrSession* session, uxrStreamId stream_id, uxrObjectId datareader_id, uxrStreamId data_stream_id, uxrDeliveryControl* delivery_control); This function requests a read from a datareader of the agent. The returned value is an identifier of the request. @@ -563,6 +579,8 @@ All received topic will have the same request identifier. The topics will be received at the callback topic through the ``run_session`` function. If there is no error with the request data, the topics will be received generating a status callback with the value ``UXR_STATUS_OK``. If there is an error, a status error will be sent by the agent. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 6841cf98..e81fde54 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -96,7 +96,7 @@ We can do this calling *Create participant* operation: uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); const char* participant_ref = "default participant"; - uint16_t participant_req = uxr_write_create_participant_ref(&session, reliable_out, participant_id, participant_ref, UXR_REPLACE); + uint16_t participant_req = uxr_buffer_create_participant_ref(&session, reliable_out, participant_id, participant_ref, UXR_REPLACE); In any XRCE Operation that creates an entity, an `Object ID` is necessary. It is used to represent and manage the entity in the *Client* side. @@ -114,7 +114,7 @@ Once the `Participant` has been created, we can use `Create topic` operation for uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = uxr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); + uint16_t topic_req = uxr_buffer_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); As any other XRCE Operation used to create an entity, an Object ID must be specify to represent the entity. The ``participant_id`` is the participant where the Topic will be registered. @@ -130,11 +130,11 @@ We create a publisher or subscriber on a participant entity, so it is necessary uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); const char* publisher_xml = ""; - uint16_t publisher_req = uxr_write_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); + uint16_t publisher_req = uxr_buffer_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); const char* subscriber_xml = ""; - uint16_t subscriber_req = uxr_write_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); + uint16_t subscriber_req = uxr_buffer_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); DataWriters & DataReaders ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -147,11 +147,11 @@ The configuration about how these `DataReaders` and data writers works is contai uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); const char* datawriter_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datawriter_req = uxr_write_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); + uint16_t datawriter_req = uxr_buffer_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datareader_req = uxr_write_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); + uint16_t datareader_req = uxr_buffer_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); Agent response ^^^^^^^^^^^^^^ @@ -239,7 +239,7 @@ Current implementation sends one topic to the client for each read data operatio uxrDeliveryControl delivery_control = {0}; delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED; - uint16_t read_data_req = uxr_write_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); + uint16_t read_data_req = uxr_buffer_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); In order to configure how the agent will send the topic, we must set the input stream. In this case, we use the input reliable stream previously defined. ``datareader_id`` corresponds with the `DataDeader` entity used for receiving the data. diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 83752894..2203ab41 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -71,19 +71,19 @@ The code of the *PublishHelloWorldClient* is the following: // Create entities uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); const char* participant_ref = "default participant"; - uint16_t participant_req = uxr_write_create_participant_ref(&session, reliable_out, participant_id, participant_ref, UXR_REPLACE); + uint16_t participant_req = uxr_buffer_create_participant_ref(&session, reliable_out, participant_id, participant_ref, UXR_REPLACE); uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = uxr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); + uint16_t topic_req = uxr_buffer_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); const char* publisher_xml = ""; - uint16_t publisher_req = uxr_write_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); + uint16_t publisher_req = uxr_buffer_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); const char* datawriter_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datawriter_req = uxr_write_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); + uint16_t datawriter_req = uxr_buffer_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); // Send create entities message and wait its status uint8_t status[4]; @@ -190,19 +190,19 @@ The code of the *SubscriberHelloWorldClient* is the following: // Create entities uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); const char* participant_ref = "default participant"; - uint16_t participant_req = uxr_write_create_participant_ref(&session, reliable_out, participant_id, 0, participant_ref, UXR_REPLACE); + uint16_t participant_req = uxr_buffer_create_participant_ref(&session, reliable_out, participant_id, 0, participant_ref, UXR_REPLACE); uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = uxr_write_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); + uint16_t topic_req = uxr_buffer_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); const char* subscriber_xml = ""; - uint16_t subscriber_req = uxr_write_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); + uint16_t subscriber_req = uxr_buffer_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datareader_req = uxr_write_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); + uint16_t datareader_req = uxr_buffer_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); // Send create entities message and wait its status uint8_t status[4]; @@ -216,7 +216,7 @@ The code of the *SubscriberHelloWorldClient* is the following: // Request topics uxrDeliveryControl delivery_control = {0}; delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED; - uint16_t read_data_req = uxr_write_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); + uint16_t read_data_req = uxr_buffer_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); // Read topics bool connected = true; From 9d71d2536f61fdc502bbefc5756a2dff5d3b0d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Wed, 17 Oct 2018 14:05:28 +0200 Subject: [PATCH 10/16] api change: configure by create (#10) --- docs/client.rst | 22 +++++++++++----------- docs/getting_started.rst | 10 +++++----- docs/quickstart.rst | 12 ++++++------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index d39e4857..523715da 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -389,7 +389,7 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ .. code-block:: c - uint16_t uxr_buffer_configure_participant_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uint16_t domain, const char* xml, uint8_t mode); + uint16_t uxr_buffer_create_participant_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uint16_t domain, const char* xml, uint8_t mode); Creates a `participant` entity in the agent. The message is only written into the stream buffer. @@ -410,7 +410,7 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux .. code-block:: c - uint16_t uxr_buffer_configure_topic_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_create_topic_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); Creates a `topic` entity in the agent. The message is only written into the stream buffer. @@ -431,9 +431,9 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux .. code-block:: c - uint16_t uxr_buffer_configure_publisher_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_create_publisher_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); -Create a `publisher` entity in the agent. +Creates a `publisher` entity in the agent. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -452,9 +452,9 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux .. code-block:: c - uint16_t uxr_buffer_configure_subscriber_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_create_subscriber_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); -Create a `publisher` entity in the agent. +Creates a `publisher` entity in the agent. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -473,9 +473,9 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux .. code-block:: c - uint16_t uxr_buffer_configure_datawriter_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId publisher_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_create_datawriter_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId publisher_id, const char* xml, uint8_t mode); -Create a `datawriter_id` entity in the agent. +Creates a `datawriter_id` entity in the agent. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -494,9 +494,9 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux .. code-block:: c - uint16_t uxr_buffer_configure_datareader_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId subscriber_id, const char* xml, uint8_t mode); + uint16_t uxr_buffer_create_datareader_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId subscriber_id, const char* xml, uint8_t mode); -Create a `datareader` entity in the agent. +Creates a `datareader` entity in the agent. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -524,7 +524,7 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ uint16_t uxr_buffer_create_participant_ref(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, const char* ref, uint8_t mode); -Create a `datareader` entity in the agent. +Creates a `datareader` entity in the agent. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. diff --git a/docs/getting_started.rst b/docs/getting_started.rst index e81fde54..a112cb81 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -114,7 +114,7 @@ Once the `Participant` has been created, we can use `Create topic` operation for uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = uxr_buffer_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); + uint16_t topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); As any other XRCE Operation used to create an entity, an Object ID must be specify to represent the entity. The ``participant_id`` is the participant where the Topic will be registered. @@ -130,11 +130,11 @@ We create a publisher or subscriber on a participant entity, so it is necessary uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); const char* publisher_xml = ""; - uint16_t publisher_req = uxr_buffer_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); + uint16_t publisher_req = uxr_buffer_create_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); const char* subscriber_xml = ""; - uint16_t subscriber_req = uxr_buffer_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); + uint16_t subscriber_req = uxr_buffer_create_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); DataWriters & DataReaders ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -147,11 +147,11 @@ The configuration about how these `DataReaders` and data writers works is contai uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); const char* datawriter_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datawriter_req = uxr_buffer_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); + uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datareader_req = uxr_buffer_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); + uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); Agent response ^^^^^^^^^^^^^^ diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 2203ab41..bfd68a8c 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -75,15 +75,15 @@ The code of the *PublishHelloWorldClient* is the following: uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = uxr_buffer_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); + uint16_t topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); const char* publisher_xml = ""; - uint16_t publisher_req = uxr_buffer_configure_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); + uint16_t publisher_req = uxr_buffer_create_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); const char* datawriter_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datawriter_req = uxr_buffer_configure_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); + uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); // Send create entities message and wait its status uint8_t status[4]; @@ -194,15 +194,15 @@ The code of the *SubscriberHelloWorldClient* is the following: uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = uxr_buffer_configure_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); + uint16_t topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); const char* subscriber_xml = ""; - uint16_t subscriber_req = uxr_buffer_configure_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); + uint16_t subscriber_req = uxr_buffer_create_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datareader_req = uxr_buffer_configure_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); + uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); // Send create entities message and wait its status uint8_t status[4]; From 84441b7e3096bd14b887dd877d0a36e15dc69cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Fri, 19 Oct 2018 10:44:14 +0200 Subject: [PATCH 11/16] Refs 3426. Optimization doc (#9) * Refs 3426. First attempt to optimization doc * Modified with comments for acept pull request. --- docs/index.rst | 1 + docs/optimization.rst | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 docs/optimization.rst diff --git a/docs/index.rst b/docs/index.rst index fe81f56a..be79b772 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -63,6 +63,7 @@ Index entities operations deployment + optimization .. toctree:: :caption: Release Notes diff --git a/docs/optimization.rst b/docs/optimization.rst new file mode 100644 index 00000000..d4a1061f --- /dev/null +++ b/docs/optimization.rst @@ -0,0 +1,37 @@ +Memory optimization +=================== + +Executable code size +-------------------- +In order to manage the executable code size, the library can be compiled enabling or disabling several profiles. +To add or remove a profile from the library, edit the ``client.config`` file. +More information can be found at: :ref:`micro_xrce_dds_client_label`. + +Runtime size +------------ +The client is dynamic memory free and static memory free. +This implies that all memory charge depends only on how the stack grows during the execution. +To control the stack, there are some values that can be modified and that impact to a large degree: + +Stream buffers +~~~~~~~~~~~~~~ +1. Make sure you defined only the streams that will be used. + You can define a maximun `127` best effort streams and `128` reliable streams, + but for the majory of purposes, only one stream of either best effort or reliable can be used. + +2. The history of a reliable streams is used for recovering from lost messages and speeding up the communication. + For output streams, more history value will allow writing and send more messages without wait confirmation. + If a history of an output stream is full (no messages were still confirmed by the agent), no more messages can be storaged into the stream. + For input streams, the history is used for recovering faster when the messages are lost using less extra band-width. + If your connection is highly reliable and to save memory is a priority, a reduced history can be used. + +3. The size of the stream corresponds to the total reserved memory for the stream. + The size must be according to the next value: ``MAX_MESSAGE_SIZE * HISTORY``. + The ``MAX_MESSAGE_SIZE`` must be less or equal than the transport MTU used. + +Transport MTUs +~~~~~~~~~~~~~~ +Each transport have a different MTU. +The MTU value can be defined into the ``client.config`` file. +The MTU will represent the ``MAX_MESSAGE_SIZE`` that can be send or received. +The transport uses the MTU value to create an internal buffer. From 6b2d3388bf28e7a8967f1c6f43e84639ed2add69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Fri, 19 Oct 2018 12:14:57 +0200 Subject: [PATCH 12/16] Refs #3426. Applied the majority comments of Gasco review. (#11) --- docs/client.rst | 18 +-- docs/deployment.rst | 2 +- docs/entities.rst | 10 +- docs/getting_started.rst | 77 ++++++++---- docs/quickstart.rst | 257 +++++++++++++++++++++++++-------------- docs/shapes_demo.rst | 1 + 6 files changed, 233 insertions(+), 132 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index 523715da..7aa7b0be 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -14,7 +14,7 @@ Profiles The client library follows a profile concept that enables to choose add or remove some features in configuration time. This allows to reduce the client library size, if there are features that are not used. -The profiles can be choosen in ``client.config`` and start with the prefix ``PROFILE``. +The profiles can be chosen in ``client.config`` and start with the prefix ``PROFILE``. As part of these profiles, you can choose between several transport layers. Communication with the agent is done through the transport you choose. @@ -183,7 +183,7 @@ This function logs in a session, enabling any other XRCE communication with the bool uxr_delete_session(uxrSession* session); -Deletes session previously created. +Deletes a session previously created. All `XRCE` entities created with the session will be removed. This function logs out a session, disabling any other `XRCE` communication with the agent. @@ -629,14 +629,14 @@ The discovery phase can be performed before the `uxr_create_session` call in ord These functions are enabled when PROFILE_DISCOVERY is enabled in the ``client.config`` file. The declaration of these functions can be found in ``uxr/client/profile/discovery/discovery.h``. -bool uxr_discovery_agents_multicast(uint32_t attemps, int period, uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* choosen); +bool uxr_discovery_agents_multicast(uint32_t attemps, int period, uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* chosen); ------ .. code-block:: c bool uxr_discovery_agents_multicast(uint32_t attempts, int period, - uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* choosen); + uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* chosen); Searches into the network using multicast ip "239.255.0.2" and port 7400 (default used by the agent) in order to discover agents. @@ -645,17 +645,17 @@ Searches into the network using multicast ip "239.255.0.2" and port 7400 (defaul :on_agent_func: The callback function that will be called when an agent was discovered. The callback returns a boolean value. A `true` means that the discovery rutine will be end and exit. - The current agent will be selected as *choosen*. + The current agent will be selected as *chosen*. A `false` implies that the discovery rutine must to continue searching agents. :args: User arguments passed to the callback function. -:choosen: If the callback function was returned `true`, this value will contains the agent value of the callback. +:chosen: If the callback function was returned `true`, this value will contains the agent value of the callback. ------ .. code-block:: c bool uxr_discovery_agents_unicast(uint32_t attempts, int period, - uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* choosen, + uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* chosen, const uxrAgentAddress* agent_list, size_t agent_list_size); Searches into the network using a list of unicast directions in order to discover agents. @@ -665,10 +665,10 @@ Searches into the network using a list of unicast directions in order to discove :on_agent_func: The callback function that will be called when an agent was discovered. The callback returns a boolean value. A ``true`` means that the discovery rutine will be end and exit. - The current agent will be selected as *choosen*. + The current agent will be selected as *chosen*. A ``false`` implies that the discovery rutine must to continue searching agents. :args: User arguments passed to the callback function. -:choosen: If the callback function was returned ``true``, this value will contains the agent value of the callback. +:chosen: If the callback function was returned ``true``, this value will contains the agent value of the callback. :agent_list: The list of address where discover agent. By default the agents will be listen at **port 7400** the discovery messages.. :agent_list_size: The size of the ``agent_list``. diff --git a/docs/deployment.rst b/docs/deployment.rst index 61c2467c..c2d49789 100644 --- a/docs/deployment.rst +++ b/docs/deployment.rst @@ -13,7 +13,7 @@ One for configurating the entities in the agent, and run possibly once, only for And other/s, that logs in the same session as the configure client (sharing the entities) and only publishes or subscribes data. This way allows to create easy clients in production only with the purpose of send and receive data. -Related to it, exists the concept of `profile` that allow to build the client library only with the behavior choosen (only publish or only suscribe, for example). +Related to it, exists the concept of `profile` that allows to build the client library only with the behavior chosen (only publish or only subscribe, for example). See :ref:`micro_xrce_dds_client_label` for more information about this. Next diagram shows an example about how to configure the enviroment using a `configurator client`. diff --git a/docs/entities.rst b/docs/entities.rst index 135490b6..8884ccc0 100644 --- a/docs/entities.rst +++ b/docs/entities.rst @@ -3,12 +3,12 @@ Entities ======== -The protocol under *Micro XRCE-DDS* (XRCE), defines entities that have a direct correspondence with their analogous actor on *Fast RTPS* (DDS). -The entities manage the communication between *Micro XRCE-DDS Client* and the DDS Global Data Space. -Entities are stored in the *Micro XRCE-DDS Agent* and the *Micro XRCE-DDS Client* can create, use and destroy these entities. +The protocol under `Micro XRCE-DDS` (XRCE), defines entities that have a direct correspondence with their analogous actors on `Fast RTPS` (DDS). +The entities manage the communication between `Micro XRCE-DDS Client` and the DDS Global Data Space. +Entities are stored in the `Micro XRCE-DDS Agent` and the `Micro XRCE-DDS Client` can create, use and destroy these entities. -The entities are uniquely identified by an ID called `Object ID`. `Object ID` is the way a *Client* refers to them inside an Agent. -In most of the *Client* requests operations is necessary to specify an ID referring to one of the *Client* entities stored in the *Agent*. +The entities are uniquely identified by an ID called `Object ID`. `Object ID` is the way a `Client` refers to them inside an Agent. +In most of the `Client` request operations is necessary to specify an ID referring to one of the `Client` entities stored in the `Agent`. Type of Entities ---------------- diff --git a/docs/getting_started.rst b/docs/getting_started.rst index a112cb81..5a4f1117 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -39,19 +39,19 @@ Also, we will specify the max buffer for the streams and its historical associat #define STREAM_HISTORY 8 #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY -First, we need to create a Session indicating the transport to use. -The agent must be configured for listening from udp at port 2018. +Before create a Session we need to indicate the transport to use (the agent must be configured for listening from udp at port 2018). .. code-block:: C uxrUDPTransport transport; - if(!uxr_init_udp_transport(&transport, "127.0.0.1", 2018)) + uxrUDPPlatform udp_platform; + if(!uxr_init_udp_transport(&transport, &udp_platform, "127.0.0.1", 2018)) { printf("Error at create transport.\n"); return 1; } -Next, we will a session that allow us interact with the agent: +Next, we will create a session that allow us interact with the agent: .. code-block:: C @@ -95,13 +95,19 @@ We can do this calling *Create participant* operation: .. code-block:: C uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); - const char* participant_ref = "default participant"; - uint16_t participant_req = uxr_buffer_create_participant_ref(&session, reliable_out, participant_id, participant_ref, UXR_REPLACE); - -In any XRCE Operation that creates an entity, an `Object ID` is necessary. + const char* participant_xml = "" + "" + "" + "default_xrce_participant" + "" + "" + ""; + uint16_t participant_req = uxr_buffer_create_participant_ref(&session, reliable_out, participant_id, participant_xml, UXR_REPLACE); + +In any `XRCE Operation` that creates an entity, an `Object ID` is necessary. It is used to represent and manage the entity in the *Client* side. -The reference is the identifier of a DDS entity in the *Agent* side. -Each operation, return a `Request ID`. +In this case we will create the entity by its XML description, but also could be done by a reference of the entity in the agent. +Each operation, returns a `Request ID`. This identifier of the operation can be used later for associating the status with the operation. In this case, the operation has been written into the stream ``reliable_out``. Later, in the ``run_session`` function, the data written in the stream will be sent to the agent. @@ -113,10 +119,15 @@ Once the `Participant` has been created, we can use `Create topic` operation for .. code-block:: C uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); - const char* topic_xml = "HelloWorldTopicHelloWorld"; + const char* topic_xml = "" + "" + "HelloWorldTopic" + "HelloWorld" + "" + ""; uint16_t topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); -As any other XRCE Operation used to create an entity, an Object ID must be specify to represent the entity. +As any other XRCE Operation used to create an entity, an Object ID must be specified to represent the entity. The ``participant_id`` is the participant where the Topic will be registered. In order to determine which topic will be used, an XML is sent to the agent for creating and defining the Topic in the DDS Global Data Space. That definition consists of a name and a type. @@ -129,13 +140,15 @@ We create a publisher or subscriber on a participant entity, so it is necessary .. code-block:: C uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); - const char* publisher_xml = ""; + const char* publisher_xml = ""; uint16_t publisher_req = uxr_buffer_create_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); - const char* subscriber_xml = ""; + const char* subscriber_xml = ""; uint16_t subscriber_req = uxr_buffer_create_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); +The `Publisher` and `Subscriber` xml information is given when the `DataWriter` and `DataReader` be created. + DataWriters & DataReaders ^^^^^^^^^^^^^^^^^^^^^^^^^ Analogous to publishers and subscribers entities, we create the `DataWriters` and `DataReaders` entities. @@ -146,11 +159,27 @@ The configuration about how these `DataReaders` and data writers works is contai .. code-block:: C uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); - const char* datawriter_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; + const char* datawriter_xml = "" + "" + "" + "NO_KEY" + "HelloWorldTopic" + "HelloWorld" + "" + "" + ""; uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); - const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; + const char* datareader_xml = "" + "" + "" + "NO_KEY" + "HelloWorldTopic" + "HelloWorld" + "" + "" + ""; uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); Agent response @@ -158,10 +187,11 @@ Agent response In operations such as create session, create entity or request data from the *Agent*, an status is sent from the *Agent* to the *Client* indicating what happened. -For `Create session` or `Detele session` operations the status value is storage into the ``session.info.last_request_status``. +For `Create session` or `Detele session` operations the status value is stored into the ``session.info.last_request_status``. For the rest of the operations, the status are sent to the input reliable stream ``0x80``, that is, the first input reliable stream created, with index 0. The different status values that the agent can send to the client are the following: +(You can see the definitions in ``uxr/client/core/sesssion/session_info.h`` file) .. code-block:: C @@ -175,6 +205,7 @@ The different status values that the agent can send to the client are the follow UXR_STATUS_ERR_INVALID_DATA UXR_STATUS_ERR_INCOMPATIBLE UXR_STATUS_ERR_RESOURCES + UXR_STATUS_NONE (never send, only used when the status is known) The status can be handle by the ``on_status_callback`` callback (configured in ``uxr_set_status_callback`` function) or by the ``run_session_until_all_status`` as we will see. @@ -189,7 +220,7 @@ The status can be handle by the ``on_status_callback`` callback (configured in ` } The ``run_session`` functions are the main functions of the `Micro RTP Client` library. -They performs serveral things: send the stream data to the agent, listen data from the agent, call callbacks, and manage the reliable connection. +They performs serveral tasks: send the stream data to the agent, listen data from the agent, call callbacks, and manage the reliable connection. There are five variations of ``run_session`` function: - ``uxr_run_session_time`` - ``uxr_run_session_until_timeout`` @@ -197,7 +228,7 @@ There are five variations of ``run_session`` function: - ``uxr_run_session_until_all_status`` - ``uxr_run_session_until_one_status`` -Here we use the ``uxr_run_session_until_all_status`` variation that will performs these actions until all status have been confirmed or the timeout has been reached. +Here we use the ``uxr_run_session_until_all_status`` variation that will perform these actions until all status have been confirmed or the timeout has been reached. This function will return ``true`` in case all status were `OK`. After call this function, the status can be read from the ``status`` array previously declared. @@ -224,7 +255,7 @@ If the stream is available and the topic fits in it, the function will initializ Once the ``ucdrBuffer`` is prepared, the topic can be serialized into it. We are careless about ``uxr_prepare_output_stream`` return value because the serialization only will occur if the ``ucdrBuffer` is valid`` -After the write function, as happend with the creation of entities, the topic has been serialized into the buffer but it has not been sent yet. +After the write function, as happened with the creation of entities, the topic has been serialized into the buffer but it has not been sent yet. To send the topic is necessary call to a ``run_session`` function. In this case, we call to ``uxr_run_session_until_confirmed_delivery`` that will wait until the message was confirmed or until the timeout has been reached. @@ -259,12 +290,12 @@ The ``run_session`` function will call the topic callback each time a topic will } To know which kind of Topic has been received, we can use the ``object_id`` parameter or the ``request_id``. -This id of the ``object_id`` corresponds to the DataReader that has read the Topic. -The ``args`` argument correspond to user free data. +The ``id`` of the ``object_id`` corresponds to the `DataReader` that has read the Topic, so it can be useful to discretize among diferent topics. +The ``args`` argument correspond to user free data, that has been given at `uxr_set_status_callback` function. Closing the Client ^^^^^^^^^^^^^^^^^^ -To close a *Client*, we must perform two steps. +To close a `Client`, we must perform two steps. First, we need to tell the agent that the session is no longer available. This is done sending the next message: diff --git a/docs/quickstart.rst b/docs/quickstart.rst index bfd68a8c..73d44277 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -18,15 +18,31 @@ First of all, we launch the `Agent`. For this example, the `Client` - `Agent` co Along with the `Agent`, the `PublishHelloWorldClient` example provided in the source code is launched. This `Client` example will publish in the DDS World the HelloWorld topic. :: - $ examples/PublishHelloWorld/PublishHelloWorldClient + $ examples/uxr/client/PublishHelloWorld/PublishHelloWorldClient The code of the *PublishHelloWorldClient* is the following: .. code-block:: C - #include "HelloWorldWriter.h" + // Copyright 2017 Proyectos y Sistemas de Mantenimiento SL (eProsima). + // + // Licensed under the Apache License, Version 2.0 (the "License"); + // you may not use this file except in compliance with the License. + // You may obtain a copy of the License at + // + // http://www.apache.org/licenses/LICENSE-2.0 + // + // Unless required by applicable law or agreed to in writing, software + // distributed under the License is distributed on an "AS IS" BASIS, + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + // See the License for the specific language governing permissions and + // limitations under the License. + + #include "HelloWorld.h" #include + #include + #include #include //strcmp #include //atoi @@ -46,7 +62,8 @@ The code of the *PublishHelloWorldClient* is the following: // Transport uxrUDPTransport transport; - if(!uxr_init_udp_transport(&transport, "127.0.0.1", 2018)) + uxrUDPPlatform udp_platform; + if(!uxr_init_udp_transport(&transport, &udp_platform, "127.0.0.1", 2018)) { printf("Error at create transport.\n"); return 1; @@ -70,19 +87,38 @@ The code of the *PublishHelloWorldClient* is the following: // Create entities uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); - const char* participant_ref = "default participant"; - uint16_t participant_req = uxr_buffer_create_participant_ref(&session, reliable_out, participant_id, participant_ref, UXR_REPLACE); + const char* participant_xml = "" + "" + "" + "default_xrce_participant" + "" + "" + ""; + uint16_t participant_req = uxr_buffer_create_participant_xml(&session, reliable_out, participant_id, 0, participant_xml, UXR_REPLACE); uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); - const char* topic_xml = "HelloWorldTopicHelloWorld"; + const char* topic_xml = "" + "" + "HelloWorldTopic" + "HelloWorld" + "" + ""; uint16_t topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID); - const char* publisher_xml = ""; + const char* publisher_xml = ""; uint16_t publisher_req = uxr_buffer_create_publisher_xml(&session, reliable_out, publisher_id, participant_id, publisher_xml, UXR_REPLACE); uxrObjectId datawriter_id = uxr_object_id(0x01, UXR_DATAWRITER_ID); - const char* datawriter_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; + const char* datawriter_xml = "" + "" + "" + "NO_KEY" + "HelloWorldTopic" + "HelloWorld" + "" + "" + ""; uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, reliable_out, datawriter_id, publisher_id, datawriter_xml, UXR_REPLACE); // Send create entities message and wait its status @@ -106,7 +142,7 @@ The code of the *PublishHelloWorldClient* is the following: uxr_prepare_output_stream(&session, reliable_out, datawriter_id, &mb, topic_size); HelloWorld_serialize_topic(&mb, &topic); - connected = uxr_run_session_until_time(&session, 1000); + connected = uxr_run_session_time(&session, 1000); if(connected) { printf("Sent topic: %s, id: %i\n", topic.message, topic.index); @@ -122,117 +158,150 @@ The code of the *PublishHelloWorldClient* is the following: After it, we will launch the *SubscriberHelloWorldClient*. This `Client` example will subscribe to HelloWorld topic from the DDS World. :: - $ examples/SubscriberHelloWorld/SubscribeHelloWorldClient + $ examples/uxr/client/SubscriberHelloWorld/SubscribeHelloWorldClient The code of the *SubscriberHelloWorldClient* is the following: .. code-block:: C - #include "HelloWorld.h" + // Copyright 2017 Proyectos y Sistemas de Mantenimiento SL (eProsima). + // + // Licensed under the Apache License, Version 2.0 (the "License"); + // you may not use this file except in compliance with the License. + // You may obtain a copy of the License at + // + // http://www.apache.org/licenses/LICENSE-2.0 + // + // Unless required by applicable law or agreed to in writing, software + // distributed under the License is distributed on an "AS IS" BASIS, + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + // See the License for the specific language governing permissions and + // limitations under the License. + + #include "HelloWorld.h" - #include - #include //strcmp - #include //atoi - #include + #include + #include //strcmp + #include //atoi + #include - #define STREAM_HISTORY 8 - #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY + #define STREAM_HISTORY 8 + #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY - void on_topic(uxrSession* session, uxrObjectId object_id, uint16_t request_id, uxrStreamId stream_id, struct ucdrBuffer* mb, void* args) - { - (void) session; (void) object_id; (void) request_id; (void) stream_id; + void on_topic(uxrSession* session, uxrObjectId object_id, uint16_t request_id, uxrStreamId stream_id, struct ucdrBuffer* mb, void* args) + { + (void) session; (void) object_id; (void) request_id; (void) stream_id; - HelloWorld topic; - HelloWorld_deserialize_topic(mb, &topic); + HelloWorld topic; + HelloWorld_deserialize_topic(mb, &topic); - printf("Received topic: %s, id: %i\n", topic.message, topic.index); + printf("Received topic: %s, id: %i\n", topic.message, topic.index); - uint32_t* count_ptr = (uint32_t*) args; - (*count_ptr)++; - } + uint32_t* count_ptr = (uint32_t*) args; + (*count_ptr)++; + } - int main(int args, char** argv) + int main(int args, char** argv) + { + if(args >= 2 && (0 == strcmp("-h", argv[1]) || 0 == strcmp("--help", argv[1]) || 0 == atoi(argv[1]))) { - if(args >= 2 && (0 == strcmp("-h", argv[1]) || 0 == strcmp("--help", argv[1]) || 0 == atoi(argv[1]))) - { - printf("usage: program [-h | --help | ]\n"); - return 0; - } - - uint32_t count = 0; - uint32_t max_topics = (args == 2) ? (uint32_t)atoi(argv[1]) : UINT32_MAX; - - // Transport - uxrUDPTransport transport; - if(!uxr_init_udp_transport(&transport, "127.0.0.1", 2018)) - { - printf("Error at create transport.\n"); - return 1; - } - - // Session - uxrSession session; - uxr_init_session(&session, &transport.comm, 0xCCCCDDDD); - uxr_set_topic_callback(&session, on_topic, &count); - if(!uxr_create_session(&session)) - { - printf("Error at create session.\n"); - return 1; - } + printf("usage: program [-h | --help | ]\n"); + return 0; + } - // Streams - uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; - uxrStreamId reliable_out = uxr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + uint32_t count = 0; + uint32_t max_topics = (args == 2) ? (uint32_t)atoi(argv[1]) : UINT32_MAX; - uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; - uxrStreamId reliable_in = uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); + // Transport + uxrUDPTransport transport; + uxrUDPPlatform udp_platform; + if(!uxr_init_udp_transport(&transport, &udp_platform, "127.0.0.1", 2018)) + { + printf("Error at create transport.\n"); + return 1; + } - // Create entities - uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); - const char* participant_ref = "default participant"; - uint16_t participant_req = uxr_buffer_create_participant_ref(&session, reliable_out, participant_id, 0, participant_ref, UXR_REPLACE); + // Session + uxrSession session; + uxr_init_session(&session, &transport.comm, 0xCCCCDDDD); + uxr_set_topic_callback(&session, on_topic, &count); + if(!uxr_create_session(&session)) + { + printf("Error at create session.\n"); + return 1; + } - uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); - const char* topic_xml = "HelloWorldTopicHelloWorld"; - uint16_t topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); + // Streams + uint8_t output_reliable_stream_buffer[BUFFER_SIZE]; + uxrStreamId reliable_out = uxr_create_output_reliable_stream(&session, output_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); - uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); - const char* subscriber_xml = ""; - uint16_t subscriber_req = uxr_buffer_create_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); + uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; + uxrStreamId reliable_in = uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); - uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); - const char* datareader_xml = "NO_KEYHelloWorldTopicHelloWorldKEEP_LAST5TRANSIENT_LOCAL"; - uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); + // Create entities + uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID); + const char* participant_xml = "" + "" + "" + "default_xrce_participant" + "" + "" + ""; + uint16_t participant_req = uxr_buffer_create_participant_xml(&session, reliable_out, participant_id, 0, participant_xml, UXR_REPLACE); - // Send create entities message and wait its status - uint8_t status[4]; - uint16_t requests[4] = {participant_req, topic_req, subscriber_req, datareader_req}; - if(!uxr_run_session_until_all_status(&session, 1000, requests, status, 4)) - { - printf("Error at create entities: participant: %i topic: %i subscriber: %i datareader: %i\n", status[0], status[1], status[2], status[3]); - return 1; - } + uxrObjectId topic_id = uxr_object_id(0x01, UXR_TOPIC_ID); + const char* topic_xml = "" + "" + "HelloWorldTopic" + "HelloWorld" + "" + ""; + uint16_t topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id, participant_id, topic_xml, UXR_REPLACE); - // Request topics - uxrDeliveryControl delivery_control = {0}; - delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED; - uint16_t read_data_req = uxr_buffer_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); + uxrObjectId subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID); + const char* subscriber_xml = ""; + uint16_t subscriber_req = uxr_buffer_create_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); + + uxrObjectId datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID); + const char* datareader_xml = "" + "" + "" + "NO_KEY" + "HelloWorldTopic" + "HelloWorld" + "" + "" + ""; + uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id, subscriber_id, datareader_xml, UXR_REPLACE); - // Read topics - bool connected = true; - while(connected && count < max_topics) - { - uint8_t read_data_status; - connected = uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); - } + // Send create entities message and wait its status + uint8_t status[4]; + uint16_t requests[4] = {participant_req, topic_req, subscriber_req, datareader_req}; + if(!uxr_run_session_until_all_status(&session, 1000, requests, status, 4)) + { + printf("Error at create entities: participant: %i topic: %i subscriber: %i datareader: %i\n", status[0], status[1], status[2], status[3]); + return 1; + } - // Delete resources - uxr_delete_session(&session); - uxr_close_udp_transport(&transport); + // Request topics + uxrDeliveryControl delivery_control = {0}; + delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED; + uint16_t read_data_req = uxr_buffer_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); - return 0; + // Read topics + bool connected = true; + while(connected && count < max_topics) + { + uint8_t read_data_status; + connected = uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1); } + // Delete resources + uxr_delete_session(&session); + uxr_close_udp_transport(&transport); + + return 0; + } At this moment, the subscriber will receive the topics that are sending by the publisher. diff --git a/docs/shapes_demo.rst b/docs/shapes_demo.rst index 5e02883d..658a73eb 100644 --- a/docs/shapes_demo.rst +++ b/docs/shapes_demo.rst @@ -5,6 +5,7 @@ Shapes Demo `ShapesDemo `_ is an interactive example for testing how `Fast RTPS` working in the `DDS Global Data Space`. Because the aim of `Micro XRCE-DDS` is connect a `XRCE Client` to the `DDS World`, in this example we will create a client which will interact with the `Shapes Demo`. +It can be found at `examples/uxr/client/ShapeDemoClient` inside of the installation directory. This interactive client waits for user input indicating commands to execute. The available commands are the following: From a72020793698e5930e7be7424a0f5c17f84de78f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Wed, 31 Oct 2018 07:46:15 +0100 Subject: [PATCH 13/16] Added a small explanation about streams in client.rst. (#16) * Added a small explanation about streams in client.rst. * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm * Deeper explanation about the history in reliable streams. * Extended stream doc * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm * Update docs/client.rst Co-Authored-By: lemunozm --- docs/client.rst | 32 ++++++++++++++++++++++++++++++-- docs/optimization.rst | 2 ++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/client.rst b/docs/client.rst index 7aa7b0be..928b7dce 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -111,12 +111,40 @@ For incorporating the changes to your project, is necessary to run the ``cmake`` This value corresponds to the `Maximun Transmission Unit` able to send and receive by Serial. Internally a buffer is created proportional to this size. +Streams +------- +The client communication is performed by streams. +The streams can be seen as communication channels. +There are two types of streams: best effort and reliable streams and you can create several of them. + +* Best effort streams will send and receive the data leaving the reliability to the transport layer. + As a result, the best effort streams consume fewer resources than a reliable stream. + +* Reliable streams perform the communication without lost regardless of the transport layer. + To avoid message losses, the reliable streams use additional messages to confirm the delivery, along to a history of the messages sent and received. + The history is used to store messages that can not be currently processed because of the delivery order or must be sent again if the message can not be confirmed. + If the history is full: + + * The messages that will be written to the agent will be discarded until the history get space to store them. + So, the user must wait to write in those streams (they can be considered blocked). + + * The messages received from the agent will be discarded. + The library will try to recover the discarded messages requesting them to the agent (increasing the bandwidth consumption in that process). + + For that, a low history causes more messages to be discarded, increasing the data traffic because they need to be sent again. + A long history will reduce the data traffic of confirmation messages in transports with a high loss rate. + This internal management of the communication implies that a reliable stream is more expensive than best effort streams, + in both, memory and bandwidth, but is possible to play with these values using the history size. + +The streams are maybe the highest memory load part of the application. +For that, the choice of a right configuration for the application purpose is highly recommendable, especially when the target is a limited resources device. +The :ref:`optimization_label` page explain more about how to archive this. + API --- As a nomenclature, `Micro XRCE-DDS Client` API uses a ``uxr_`` prefix in all of their public API functions and ``uxr`` prefix in the types. In constants values an ``UXR_`` prefix is used. -Functions without these rules `should not` be used. -They are only for internal use. +The functions belonging to the public interface of the library are only those with the tag ``UXRDDLAPI`` in their declarations. Session ``````` diff --git a/docs/optimization.rst b/docs/optimization.rst index d4a1061f..78c1311c 100644 --- a/docs/optimization.rst +++ b/docs/optimization.rst @@ -1,3 +1,5 @@ +.. _optimization_label: + Memory optimization =================== From 4192febf231ce2723440c963d5c2544ab8f30499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Wed, 31 Oct 2018 07:48:34 +0100 Subject: [PATCH 14/16] Added features part (#15) * Added features part * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Update docs/index.rst Co-Authored-By: lemunozm * Changed support feature part. * Refs #3600. Added compiler independent feature. * Fixed image. * Update docs/index.rst Co-Authored-By: lemunozm * Updated index file. --- README.md | 7 ++-- docs/images/xrcedds_architecture.svg | 2 +- docs/index.rst | 48 ++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 67817c9b..48494b80 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,12 @@ -*eProsima Micro XRCE-DDS* is a software solution which allows to communicate eXtremely Resource Constrained Environments (XRCEs) with an existing DDS network. This implementation complies with the specification proposal, "eXtremely Resource Constrained Environments DDS (DDS-XRCE)" submitted to the Object Management Group (OMG) consortium. +*eProsima Micro XRCE-DDS* is a software solution which allows to communicate eXtremely Resource Constrained Environments (XRCEs) with an existing DDS network. +This implementation complies with the specification proposal, "eXtremely Resource Constrained Environments DDS (DDS-XRCE)" submitted to the Object Management Group (OMG) consortium. -*Micro XRCE-DDS* implements a client-server protocol to enable resource-constrained devices (clients) to take part in DDS communications. *Micro XRCE-DDS Agent* (server) makes possible this communication. The *Micro XRCE-DDS Agent* acts on behalf of the *Micro XRCE-DDS Clients* and enables them to take part as DDS publishers and/or subscribers in the DDS Global Data Space. +*Micro XRCE-DDS* implements a client-server protocol to enable resource-constrained devices (clients) to take part in DDS communications. +*Micro XRCE-DDS Agent* (server) makes possible this communication. +The *Micro XRCE-DDS Agent* acts on behalf of the *Micro XRCE-DDS Clients* and enables them to take part as DDS publishers and/or subscribers in the DDS Global Data Space. *Micro XRCE-DDS* provides both, a plug and play *Micro XRCE-DDS Agent* and an API layer which allows you to implement your *Micro XRCE-DDS Clients*. diff --git a/docs/images/xrcedds_architecture.svg b/docs/images/xrcedds_architecture.svg index 9109aacc..ae5e3071 100644 --- a/docs/images/xrcedds_architecture.svg +++ b/docs/images/xrcedds_architecture.svg @@ -1,2 +1,2 @@ -
Micro XRCE-DDS Agent
[Not supported by viewer]
XRCE-DDS
[Not supported by viewer]
RTPS
RTPS
Low Resources Device
Low Resources Device
Micro XRCE-DDS Client
<b>Micro XRCE-DDS Client</b>
XRCE-DDS
[Not supported by viewer]
Low Resources Device
Low Resources Device
Micro XRCE-DDS Client
<b>Micro XRCE-DDS Client</b>
\ No newline at end of file +
Micro XRCE-DDS Agent
[Not supported by viewer]
DDS-XRCE
[Not supported by viewer]
RTPS
RTPS
Low Resources Device
Low Resources Device
Micro XRCE-DDS Client
<b>Micro XRCE-DDS Client</b>
DDS-XRCE
[Not supported by viewer]
Low Resources Device
Low Resources Device
Micro XRCE-DDS Client
<b>Micro XRCE-DDS Client</b>
\ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index be79b772..58890f3a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,13 +10,57 @@ eProsima Micro XRCE-DDS This implementation complies with the specification proposal, "eXtremely Resource Constrained Environments DDS (DDS-XRCE)" submitted to the Object Management Group (OMG) consortium. *Micro XRCE-DDS* implements a client-server protocol to enable resource-constrained devices (clients) to take part in DDS communications. -*Micro XRCE-DDS Agent* (server) makes possible this communication. -The *Micro XRCE-DDS Agent* acts on behalf of the *Micro XRCE-DDS Clients* and enables them to take part as DDS publishers and/or subscribers in the DDS Global Data Space. +*Micro XRCE-DDS Agent* (server) makes possible this communication acting on behalf of the *Micro XRCE-DDS Clients* +and enables them to take part as DDS publishers and/or subscribers in the DDS Global Data Space. *Micro XRCE-DDS* provides both, a plug and play *Micro XRCE-DDS Agent* and an API layer which allows you to implement your *Micro XRCE-DDS Clients*. .. image:: images/xrcedds_architecture.svg +Main features +~~~~~~~~~~~~~ +High performance. + Uses a static low-level serialization library `(MicroCDR) `_ that serialize in `XCDR `_. + +Low resouces. + The client library is dynamic memory free and static memory free. + This means that the only memory charge is due to the stack growth. + It can manage a simple publisher/subscriber with less of 2KB of RAM. + Besides, the client is built with a *profiles* concept, that allows to add or remove functionality to the library changing the binary size. + +Multi-platform. + The OS dependencies are treated as pluggable modules. + The user can easily implement his platform modules to *Micro XRCE-DDS Client* library in his specific platform. + By default, the project can run over `Linux`, `Windows` and `Nuttx`. + +Compiler dependencies free. + The client library uses pure c99 standard. + No `C` compiler extensions are used. + +Free and Open Source. + The client library, the agent executable, the generator tool and internal dependencies as *MicroCDR* or *FastRTPS* are all of them free and open source. + +Easy to use. + The project comes with examples of a publisher and a subscriber, + an example of how Micro XRCE-DDS is deployed into a stage and + an interactive demo that can be used with the `ShapesDemo `_ with the purpose of understanding the DDS-XRCE protocol and making tests. + The client API is thoroughly explained, and a guided example of how to create your client application is distributed as part of the documentation. + +Implementation of the DDS-XRCE standard. + `DDS-XRCE `_ is a standard communication protocol of OMG consortium + focused on communicating eXtremely Resource Constrained Environments with the DDS world. + +Best effort and reliable communication. + *Micro XRCE-DDS* supports both, *best effort* for fast and light communication and *reliable* when the communication reliability is needed. + +Pluggable tansport layer. + Micro XRCE-DDS is not built over a specific transport as *serial* or *UDP*. + It is agnostic about the transport used, and give the user the possibility of implementing easily his tailored transport. + By default, *UPD*, *TCP*, and *serial* transports are provided. + +Commercial support + Available at `support@eprosima.com` + Installation ~~~~~~~~~~~~ To install *Micro XRCE-DDS*, follow the instructions of :ref:`installation_label` page. From 62b99ec48e7cddf738f06a147103f99fe05d5d08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Berm=C3=BAdez=20Ortega?= <34604561+julianbermudez@users.noreply.github.com> Date: Mon, 5 Nov 2018 15:52:23 +0100 Subject: [PATCH 15/16] Documentation review (#17) * Modified Subscriber example. * Refs 3297. Improved Agent documentation. * misspellings and minor fixes * Updated readme image * Minnor changes * Refs #3599. Simplified Agent XML example. * Refs 3599. Fixed some grammatical and spelling erros. * Refs #3599. Attended pull request comments. * Update docs/agent.rst Co-Authored-By: julianbermudez <34604561+julianbermudez@users.noreply.github.com> * Fix image. --- README.md | 2 +- docs/agent.rst | 84 ++++-- docs/client.rst | 379 +++++++++++++++------------ docs/conf.py | 4 +- docs/dependencies.rst | 8 +- docs/deployment.rst | 32 +-- docs/entities.rst | 4 +- docs/gen.rst | 8 +- docs/getting_started.rst | 47 ++-- docs/images/xrcedds_architecture.png | Bin 0 -> 43924 bytes docs/images/xrcedds_architecture.svg | 2 - docs/index.rst | 8 +- docs/installation.rst | 4 +- docs/introduction.rst | 19 +- docs/notes.rst | 10 +- docs/operations.rst | 15 +- docs/optimization.rst | 15 +- docs/quickstart.rst | 13 +- docs/shapes_demo.rst | 16 +- 19 files changed, 387 insertions(+), 283 deletions(-) create mode 100644 docs/images/xrcedds_architecture.png delete mode 100644 docs/images/xrcedds_architecture.svg diff --git a/README.md b/README.md index 48494b80..4e1d3da4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The *Micro XRCE-DDS Agent* acts on behalf of the *Micro XRCE-DDS Clients* and en *Micro XRCE-DDS* provides both, a plug and play *Micro XRCE-DDS Agent* and an API layer which allows you to implement your *Micro XRCE-DDS Clients*. -![Architecture](docs/images/xrcedds_architecture.svg) +![Architecture](docs/images/xrcedds_architecture.png) ## Documentation diff --git a/docs/agent.rst b/docs/agent.rst index c4782ee0..d1333fbd 100644 --- a/docs/agent.rst +++ b/docs/agent.rst @@ -3,34 +3,86 @@ Micro XRCE-DDS Agent ==================== -*Micro XRCE-DDS Agent* acts as a server between the DDS Network and *Micro XRCE-DDS Clients*. -Agents receive messages containing operations from clients. -Also agents keep track of the clients and the entities they create. -The Agent uses the entities to interact with the DDS Global Data Space on behalf of the client. +*Micro XRCE-DDS Agent* acts as a server between the DDS Network and *Micro XRCE-DDS Clients* applications. +*Agents* receive messages containing operations from *Clients*. +Also *Agents* keep track of the *Clients* and the entities they create. +The *Agent* uses the entities to interact with the DDS Global Data Space on behalf of the *Clients*. + +The communication between a *Client* and an *Agent* currently supports UDP, TCP and Serial (dependent on the platform). +While it is running, the *Agent* will attend any received request from the *Clients* and answers back with the result of that request. + +Configuration +------------- + +There are several configuration parameters which can be set at **compile time** in order to configure the *Micro RTPS Agent*. +These parameters can be selected as CMake flags (``-D=``) before the compilation. +The following is a list of the aforementioned parameters: + +``CONFIG_RELIABLE_STREAM_DEPTH`` + Specify the history of the reliable streams (default 16). + +``CONFIG_BEST_EFFORT_STREAM_DEPTH`` + Specify the history of the best-effort streams (default 16). + +``CONFIG_HEARTBEAT_PERIOD`` + Specify the ``HEARTBEAT`` message period in millisecond (default 200). + +``CONFIG_SERIAL_TRANSPORT_MTU`` + Specify the `Maximum Transmission Unit` able to send and receive by Serial (default 512). + +``CONFIG_UDP_TRANSPORT_MTU`` + Specify the `Maximum Transmission Unit` able to send and receive by UDP (default 512). + +``CONFIG_TCP_TRANSPORT_MTU`` + Specify the `Maximum Transmission Unit` able to send and receive by TCP (default 512). + +``CONFIG_TCP_MAX_CONNECTIONS`` + Specify the maximum number of connections, the *Agent* is able to manage (default 100). + +``CONFIG_TCP_MAX_BACKLOG_CONNECTIONS`` + Specify the maximum number of incoming connections (pending to establish), the *Agent* is able to manage (default 100). + -The communication between a client and an agent currently supports UDP, TCP and serial (dependent on the platform). -While running agent will attend any received request from your clients and answers back with the result of that request. Run an Agent ------------ -To run the agent you should build it as indicated in :ref:`installation_label`. +To run the *Agent* you should build it as indicated in :ref:`installation_label`. Once it is built successfully you just need to launch it executing the following command. -For serial communication: :: +For Serial communication: :: + + $ ./MicroXRCEAgent serial + +For UDP communication: :: + + $ ./MicroXRCEAgent udp [] + +For TCP communication: :: + + $ ./MicroXRCEAgent tcp [] + +If the transport used is a reliable transport, the use of a best-effort stream over it is equivalent to use a reliable stream over a not reliable transport. - $ ./MicroXRCE-DDSAgent serial +For running the *Agent* is necessary that the file ``DEFAULT_FASTRTPS_PROFILES.xml`` is located in the runtime folder. +This file contains XML profiles of `Participants`, `Topic`, `DataWriters` and `DataReaders` referenced by a ``profile_name``. +The *Client* can use the aforementioned ``profile_name`` in order to create these entities using the reference representation. +Let's see an example. -For udp communication: :: +The ``DEFAULT_FASTRTPS_PROFILES.xml`` contains the following participant profile: - $ ./MicroXRCE-DDSAgent udp +.. code-block:: xml -For tcp communication: :: + + + + default_participant + + + - $ ./MicroXRCE-DDSAgent tcp +therefore, the *Client* can use `default_xrce_participant_profile` as ``ref`` in the ``mr_buffer_create_participant_ref`` function. -If the transport used is a reliability transport, the use of a best effort stream over it is equivalent to use a reliable stream over a not reliable transport. +Default installation place this file along with the *Agent* executable into ``/usr/local/bin`` for Linux or ``C:/Program Files/microxrcedds_agent/bin`` for Windows. -For running the agent is necessary that the file ``DEFAULT_FASTRTPS_PROFILES.xml`` be located in the folder where the -agent is located. Default installation place this file along with the agent executable into ``/usr/local/bin``. diff --git a/docs/client.rst b/docs/client.rst index 928b7dce..afde215f 100644 --- a/docs/client.rst +++ b/docs/client.rst @@ -5,18 +5,18 @@ Micro XRCE-DDS Client In *Micro XRCE-DDS*, a *Client* can communicate with DDS Network as any other DDS actor could do. *Clients* can publish and subscribe to data Topics in the DDS Global Data Space. -*Micro XRCE-DDS* provides you with a C API to create *Micro XRCE-DDS Clients*. +*Micro XRCE-DDS* provides you with a C API to create *Micro XRCE-DDS Clients* application. All functions needed to set up the *Client* can be found into ``client.h`` header. This is the only header you need to include. Profiles -------- -The client library follows a profile concept that enables to choose add or remove some features in configuration time. -This allows to reduce the client library size, if there are features that are not used. +The *Client* library follows a profile concept that enables to choose, add or remove some features in configuration time. +This allows to customize the *Client* library size, if there are features that are not used. The profiles can be chosen in ``client.config`` and start with the prefix ``PROFILE``. As part of these profiles, you can choose between several transport layers. -Communication with the agent is done through the transport you choose. +Communication with the *Agent* is done through the transport you choose. The implementation of the transport depends of the platform. The next tables show the current implementation. @@ -34,8 +34,8 @@ See the current transport implementations as an example for a new custom transpo Configuration ------------- -There are several definitions for configuring and building of the client library at **compile time**. -These allow you to create a version of the library according to your requirements. +There are several definitions for configuring and building of the *Client* library at **compile time**. +These definitions allow you to create a version of the library according to your requirements. These definitions can be modified at ``client.config`` file. For incorporating the changes to your project, is necessary to run the ``cmake`` command every time the definitions change. @@ -43,7 +43,7 @@ For incorporating the changes to your project, is necessary to run the ``cmake`` Enables or disables the functions related to create entities by reference. ``PROFILE_CREATE_ENTITIES_XML=`` - Enables or disables the functions related to create entities by xml. + Enables or disables the functions related to create entities by XML. ``PROFILE_READ_ACCESS=`` Enables or disables the functions related to read topics. @@ -55,13 +55,13 @@ For incorporating the changes to your project, is necessary to run the ``cmake`` Enables or disables the functions the discovery feature. ``PROFILE_UDP_TRANSPORT=`` - Enables or disables the posibility to connect with the agent by UDP. + Enables or disables the posibility to connect with the *Agent* by UDP. ``PROFILE_TCP_TRANSPORT=`` - Enables or disables the posibility to connect with the agent by TCP. + Enables or disables the posibility to connect with the *Agent* by TCP. ``PROFILE_SERIAL_TRANSPORT=`` - Enables or disables the posibility to connect with the agent by Serial. + Enables or disables the posibility to connect with the *Agent* by Serial. ``CONFIG_MAX_OUTPUT_BEST_EFFORT_STREAMS=`` Configures the maximun output best effort streams that a session could have. @@ -72,7 +72,7 @@ For incorporating the changes to your project, is necessary to run the ``cmake`` The calls to ``uxr_create_output_reliable_stream`` function for a session must be less or equal that this value. ``CONFIG_MAX_INPUT_BEST_EFFORT_STREAMS=`` - Configure the maximun input best effort streams that a session could have. + Configures the maximun input best effort streams that a session could have. The calls to ``uxr_create_input_best_effort_stream`` function for a session must be less or equal that this value. ``CONFIG_MAX_INPUT_RELIABLE_STREAMS=`` @@ -94,21 +94,21 @@ For incorporating the changes to your project, is necessary to run the ``cmake`` It is measured in milliseconds. ``CONFIG_MACHINE_ENDIANNESS=`` - This value must be correspond to the memory endianness of the device in which the client is running. + This value must be correspond to the memory endianness of the device in which the *Client* is running. `0` implies that the machine is little endian and `1` implies big endian. It this entry is not in the ``client.config`` the build system will get this value from the machine that is compiling the library. - For cross compiling, you must set this value manually with the endianness of the device that run the client. + For cross compiling, you must set this value manually with the endianness of the device that run the *Client*. ``CONFIG_UDP_TRANSPORT_MTU=`` - This value corresponds to the `Maximun Transmission Unit` able to send and receive by UDP. + This value corresponds to the `Maximum Transmission Unit` able to send and receive by UDP. Internally a buffer is created with this size. ``CONFIG_TCP_TRANSPORT_MTU=`` - This value corresponds to the `Maximun Transmission Unit` able to send and receive by TCP. + This value corresponds to the `Maximum Transmission Unit` able to send and receive by TCP. Internally a buffer is created with this size. ``CONFIG_SERIAL_TRANSPORT_MTU=`` - This value corresponds to the `Maximun Transmission Unit` able to send and receive by Serial. + This value corresponds to the `Maximum Transmission Unit` able to send and receive by Serial. Internally a buffer is created proportional to this size. Streams @@ -161,9 +161,9 @@ Initializes a session structure. Once this function is called, a ``create_session`` call can be performed. :session: Session structure where manage the session data. -:key: The identifying key of the client. - All clients connected to an agent must have different key. -:comm: Communication used for connecting to the agent. +:key: The key identifier of the *Client*. + All *Clients* connected to an *Agent* must have different key. +:comm: Communication used for connecting to the *Agent*. All different transports have a common attribute uxrCommunication. This parameter can not be shared between active sessions. @@ -173,10 +173,10 @@ Once this function is called, a ``create_session`` call can be performed. void uxr_set_status_callback(uxrSession* session, uxrOnStatusFunc on_status_func, void* args); -Assigns the callback for the agent status messages. +Assigns the callback for the *Agent* status messages. :session: Session structure previously initialized. -:on_status_func: Function callback that will be called when a valid status message comes from the agent. +:on_status_func: Function callback that will be called when a valid status message comes from the *Agent*. :args: User pointer data. The args will be provided to ``on_status_func`` function. @@ -190,7 +190,7 @@ Assigns the callback for topics. The topics will be received only if a ``request_data`` function has been called. :session: Session structure previously initialized. -:on_status_func: Function callback that will be called when a valid data message comes from the agent. +:on_status_func: Function callback that will be called when a valid data message comes from the *Agent*. :args: User pointer data. The args will be provided to ``on_topic_func`` function. @@ -200,8 +200,8 @@ The topics will be received only if a ``request_data`` function has been called. bool uxr_create_session(uxrSession* session); -Creates a new session with the agent. -This function logs in a session, enabling any other XRCE communication with the agent. +Creates a new session with the *Agent*. +This function logs in a session, enabling any other XRCE communication with the *Agent*. :session: Session structure previously initialized. @@ -213,7 +213,7 @@ This function logs in a session, enabling any other XRCE communication with the Deletes a session previously created. All `XRCE` entities created with the session will be removed. -This function logs out a session, disabling any other `XRCE` communication with the agent. +This function logs out a session, disabling any other `XRCE` communication with the *Agent*. :session: Session structure previously initialized. @@ -293,13 +293,12 @@ Flashes all output streams sending the data through the transport. void uxr_run_session_time(uxrSession* session, int time); -The main library function. This function processes the internal functionality of a session. This implies: 1. Flashes all output streams sending the data through the transport. 2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. -3. Listens messages from the agent and call the associated callback if exists (a topic callback or a status callback). +3. Listens messages from the *Agent* and call the associated callback if exists (a topic callback or an status callback). The ``time`` suffix function version will perform these actions and will listen messages for a ``time`` duration. Only when the time waiting for a message overcome the ``time`` duration, the function finishes. @@ -315,13 +314,12 @@ The function will return ``true`` if the sent data have been confirmed, ``false` void uxr_run_session_until_timeout(uxrSession* session, int timeout); -The main library function. This function processes the internal functionality of a session. This implies: 1. Flashes all output streams sending the data through the transport. 2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. -3. Listens messages from the agent and call the associated callback if exists (a topic callback or a status callback). +3. Listens messages from the *Agent* and call the associated callback if exists (a topic callback or an status callback). The ``_until_timeout`` suffix function version will perform these actions until receiving one message. Once the message has been received or the timeout has been reached, the function finishes. @@ -338,20 +336,19 @@ The function will return ``true`` if has received a message, ``false`` if the ti bool uxr_run_session_until_confirm_delivery(uxrSession* session, int timeout); -The main library function. This function processes the internal functionality of a session. This implies: 1. Flashes all output streams sending the data through the transport. 2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. -3. Listenes messages from the agent and call the associated callback if exists (a topic callback or a status callback). +3. Listenes messages from the *Agent* and call the associated callback if exists (a topic callback or an status callback). -The ``_until_confirm_delivery`` suffix function version will perform these actions during ``timeout`` duration -or until the output reliable streams confirm that the sent messages have been received by the agent. +The ``_until_confirm_delivery`` suffix function version will perform these actions during ``timeout`` +or until the output reliable streams confirm that the sent messages have been received by the *Agent*. The function will return ``true`` if the sent data have been confirmed, ``false`` otherwise. :session: Session structure previously initialized. -:timeout: Maximun time for waiting to a new message, in milliseconds. +:timeout: Maximun waiting time for a new message, in milliseconds. For waiting without timeout, set the value to ``UXR_TIMEOUT_INF`` ------ @@ -360,24 +357,23 @@ The function will return ``true`` if the sent data have been confirmed, ``false` bool uxr_run_session_until_all_status(uxrSession* session, int timeout, const uint16_t* request_list, uint8_t* status_list, size_t list_size); -The main library function. This function processes the internal functionality of a session. This implies: 1. Flashes all output streams sending the data through the transport. 2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. -3. Listenes messages from the agent and call the associated callback if exists (a topic callback or a status callback). +3. Listenes messages from the *Agent* and call the associated callback if exists (a topic callback or an status callback). The ``_until_all_status`` suffix function version will perform these actions during ``timeout`` duration or until all requested status had been received. The function will return ``true`` if all status have been received and all of them have the value ``UXR_STATUS_OK`` or ``UXR_STATUS_OK_MATCHED``, ``false`` otherwise. :session: Session structure previously initialized. -:timeout: Maximun time for waiting to a new message, in milliseconds. +:timeout: Maximun waiting time for a new message, in milliseconds. For waiting without timeout, set the value to ``UXR_TIMEOUT_INF`` -:request_list: An array of request to confirm with a status. +:request_list: An array of request to confirm with an status. :status_list: An uninitialized array with the same size as ``request_list`` where the status values will be written. - The position of a status in the list corresponds to the request at the same position in ``request_list``. + The position of an status in the list corresponds to the request at the same position in ``request_list``. :list_size: The size of ``request_list`` and ``status_list`` arrays. ------ @@ -386,20 +382,19 @@ The function will return ``true`` if all status have been received and all of th bool uxr_run_session_until_one_status(uxrSession* session, int timeout, const uint16_t* request_list, uint8_t* status_list, size_t list_size); -The main library function. This function processes the internal functionality of a session. This implies: 1. Flashes all output streams sending the data through the transport. 2. If there is any reliable stream, it will perform the asociated reliable behaviour to ensure the communication. -3. Listenes messages from the agent and call the associated callback if exists (a topic callback or a status callback). +3. Listenes messages from the *Agent* and call the associated callback if exists (a topic callback or an status callback). The ``_until_one_status`` suffix function version will perform these actions during ``timeout`` duration or until one requested status had been received. The function will return ``true`` if one status have been received and has the value ``UXR_STATUS_OK`` or ``UXR_STATUS_OK_MATCHED``, ``false`` otherwise. :session: Session structure previously initialized. -:timeout: Maximun time for waiting to a new message, in milliseconds. +:timeout: Maximun waiting time for a new message, in milliseconds. For waiting without timeout, set the value to ``UXR_TIMEOUT_INF`` :request_list: An array of request that can be confirmed. :status_list: An uninitialized array with the same size as ``request_list`` where the statu value will be written. @@ -410,7 +405,7 @@ The function will return ``true`` if one status have been received and has the v Create entities by XML profile `````````````````````````````` -These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` is enabled in the ``client.config`` file. +These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` is selected in the ``client.config`` file. The declaration of these functions can be found in ``uxr/client/profile/session/create_entities_xml.h``. ------ @@ -419,7 +414,7 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ uint16_t uxr_buffer_create_participant_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uint16_t domain, const char* xml, uint8_t mode); -Creates a `participant` entity in the agent. +Creates a `participant` entity in the *Agent*. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -428,11 +423,9 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. The type must be ``UXR_PARTICIPANT_ID`` -:xml: A xml representation of the new entity. +:xml: A XML representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``UXR_REPLACE``. - It will delete the entity previously in the agent if exists. - A ``0`` value, implies that only creates the entity if it does not exists. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. ------ @@ -440,7 +433,7 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux uint16_t uxr_buffer_create_topic_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); -Creates a `topic` entity in the agent. +Creates a `topic` entity in the *Agent*. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -449,11 +442,11 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. The type must be ``UXR_TOPIC_ID`` -:xml: A xml representation of the new entity. +:participant_id: The identifier of the associated participant. + The type must be ``UXR_PARTICIPANT_ID`` +:xml: A XML representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``UXR_REPLACE``. - It will delete the entity previously in the agent if exists. - A ``0`` value, implies that only creates the entity if it does not exists. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. ------ @@ -461,7 +454,7 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux uint16_t uxr_buffer_create_publisher_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); -Creates a `publisher` entity in the agent. +Creates a `publisher` entity in the *Agent*. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -470,11 +463,11 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. The type must be ``UXR_PUBLISHER_ID`` -:xml: A xml representation of the new entity. +:participant_id: The identifier of the associated participant. + The type must be ``UXR_PARTICIPANT_ID`` +:xml: A XML representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``UXR_REPLACE``. - It will delete the entity previously in the agent if exists. - A ``0`` value, implies that only creates the entity if it does not exists. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. ------ @@ -482,7 +475,7 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux uint16_t uxr_buffer_create_subscriber_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* xml, uint8_t mode); -Creates a `publisher` entity in the agent. +Creates a `subscriber` entity in the *Agent*. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -491,11 +484,11 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. The type must be ``UXR_SUBSCRIBER_ID`` -:xml: A xml representation of the new entity. +:participant_id: The identifier of the associated participant. + The type must be ``UXR_PARTICIPANT_ID`` +:xml: A XML representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``UXR_REPLACE``. - It will delete the entity previously in the agent if exists. - A ``0`` value, implies that only creates the entity if it does not exists. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. ------ @@ -503,7 +496,7 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux uint16_t uxr_buffer_create_datawriter_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId publisher_id, const char* xml, uint8_t mode); -Creates a `datawriter_id` entity in the agent. +Creates a `datawriter` entity in the *Agent*. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -512,11 +505,11 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. The type must be ``UXR_DATAWRITER_ID`` -:xml: A xml representation of the new entity. +:publisher_id: The identifier of the associated participant. + The type must be ``UXR_PUBLISHER_ID`` +:xml: A XML representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``UXR_REPLACE``. - It will delete the entity previously in the agent if exists. - A ``0`` value, implies that only creates the entity if it does not exists. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. ------ @@ -524,7 +517,7 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux uint16_t uxr_buffer_create_datareader_xml(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId subscriber_id, const char* xml, uint8_t mode); -Creates a `datareader` entity in the agent. +Creates a `datareader` entity in the *Agent*. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -533,17 +526,17 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. The type must be ``UXR_DATAREADER_ID`` -:xml: A xml representation of the new entity. +:subscriber_id: The identifier of the associated participant. + The type must be ``UXR_SUBSCRIBER_ID`` +:xml: A XML representation of the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``UXR_REPLACE``. - It will delete the entity previously in the agent if exists. - A ``0`` value, implies that only creates the entity if it does not exists. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. ------ Create entities by reference profile ```````````````````````````````````` -These functions are enabled when ``PROFILE_CREATE_ENTITIES_REF`` is enabled in the ``client.config`` file. +These functions are enabled when ``PROFILE_CREATE_ENTITIES_REF`` is selected in the ``client.config`` file. The declaration of these functions can be found in ``uxr/client/profile/session/create_entities_ref.h``. ------ @@ -552,7 +545,7 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ uint16_t uxr_buffer_create_participant_ref(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, const char* ref, uint8_t mode); -Creates a `datareader` entity in the agent. +Creates a `participant` entity in the *Agent*. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. @@ -560,18 +553,79 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux :stream_id: The output stream ID where the message will be written. :object_id: The identifier of the new entity. Later, the entity can be referenced with this id. - The type must be ``UXR_DATAREADER_ID`` -:xml: A xml representation of the new entity. + The type must be ``UXR_PARTICIPANT_ID`` +:ref: A reference to the new entity. +:mode: Determines the creation entity mode. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. + +------ + +.. code-block:: c + + uint16_t uxr_buffer_create_topic_ref(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId participant_id, const char* ref, uint8_t mode); + +Creates a `topic` entity in the *Agent*. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. + +:session: Session structure previously initialized. +:stream_id: The output stream ID where the message will be written. +:object_id: The identifier of the new entity. + Later, the entity can be referenced with this id. + The type must be ``UXR_TOPIC_ID`` +:participant_id: The identifier of the associated participant. + The type must be ``UXR_PARTICIPANT_ID`` +:ref: A reference to the new entity. +:mode: Determines the creation entity mode. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. + +------ + +.. code-block:: c + + uint16_t uxr_buffer_create_datawriter_ref(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId publisher_id, const char* ref, uint8_t mode); + +Creates a `datawriter` entity in the *Agent*. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. + +:session: Session structure previously initialized. +:stream_id: The output stream ID where the message will be written. +:object_id: The identifier of the new entity. + Later, the entity can be referenced with this id. + The type must be ``UXR_DATAWRITER_ID`` +:publisher_id: The identifier of the associated publisher. + The type must be ``UXR_PUBLISHER_ID`` +:ref: A reference to the new entity. :mode: Determines the creation entity mode. - Currently, only soported ``UXR_REPLACE``. - It will delete the entity previously in the agent if exists. - A ``0`` value, implies that only creates the entity if it does not exists. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. + +------ + +.. code-block:: c + + uint16_t uxr_buffer_create_datareader_ref(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id, uxrObjectId subscriber_id, const char* ref, uint8_t mode); + +Creates a `datareader` entity in the *Agent*. +The message is only written into the stream buffer. +To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. + +:session: Session structure previously initialized. +:stream_id: The output stream ID where the message will be written. +:object_id: The identifier of the new entity. + Later, the entity can be referenced with this id. + The type must be ``UXR_DATAREADER_ID``. +:subscriber_id: The identifier of the associated subscriber. + The type must be ``UXR_SUBSCRIBER_ID``. +:ref: A reference to the new entity. +:mode: Determines the creation entity mode. + The Creation Mode Table decribes the entities creation behaviour according with the ``UXR_REUSE`` and ``UXR_REPLACE`` flags. ------ Create entities common profile `````````````````````````````` -These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` or ``PROFILE_CREATE_ENTITIES_REF`` are enabled in the ``client.config`` file. +These functions are enabled when ``PROFILE_CREATE_ENTITIES_XML`` or ``PROFILE_CREATE_ENTITIES_REF`` are selected in the ``client.config`` file. The declaration of these functions can be found in ``uxr/client/profile/session/common_create_entities.h``. ------ @@ -580,19 +634,19 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ uint16_t uxr_buffer_delete_entity(uxrSession* session, uxrStreamId stream_id, uxrObjectId object_id); -Removes a entity. +Removes an entity. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. -:object_id: The identifier that will be deleted. +:object_id: The identifier of the object which will be deleted. ------ Read access profile ``````````````````` -These functions are enabled when PROFILE_READ_ACCESS is enabled in the ``client.config`` file. +These functions are enabled when ``PROFILE_READ_ACCESS`` is selected in the ``client.config`` file. The declaration of these functions can be found in ``uxr/client/profile/session/read_access.h``. ------ @@ -601,18 +655,18 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ uint16_t uxr_buffer_request_data(uxrSession* session, uxrStreamId stream_id, uxrObjectId datareader_id, uxrStreamId data_stream_id, uxrDeliveryControl* delivery_control); -This function requests a read from a datareader of the agent. +This function requests a read from a datareader of the *Agent*. The returned value is an identifier of the request. All received topic will have the same request identifier. The topics will be received at the callback topic through the ``run_session`` function. -If there is no error with the request data, the topics will be received generating a status callback with the value ``UXR_STATUS_OK``. -If there is an error, a status error will be sent by the agent. +If there is no error with the request data, the topics will be received generating an status callback with the value ``UXR_STATUS_OK``. +If there is an error, an status error will be sent by the *Agent*. The message is only written into the stream buffer. To send the message is necessary call to ``uxr_flash_output_streams`` or to ``uxr_run_session`` function. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. -:object_id: The Data Reader ID that will read the topic from the DDS World. +:object_id: The `datareader` ID that will read the topic from the DDS World. :data_stream_id: The input stream ID where the data will be received. :delivery_control: Optional information about how the delivery must be. A ``NULL`` value is accepted, in this case, only one topic will be received. @@ -621,7 +675,7 @@ To send the message is necessary call to ``uxr_flash_output_streams`` or to ``ux Write access profile ```````````````````` -These functions are enabled when PROFILE_WRITE_ACCESS is enabled in the ``client.config`` file. +These functions are enabled when ``PROFILE_WRITE_ACCESS`` is selected in the ``client.config`` file. The declaration of these functions can be found in ``uxr/client/profile/session/write_access.h``. ------ @@ -632,17 +686,16 @@ The declaration of these functions can be found in ``uxr/client/profile/session/ struct ucdrBuffer* mb_topic, uint32_t topic_size); Requests a writing into a specific output stream. -For that this function will initialize a ``ucdrBuffer`` struct where a topic of ``topic_size`` size must be serialized. -If the returned value is ``true``, exists the necessary gap for writing a ``topic_size`` bytes into the stream. -If the returned value is ``false``, the topic can no be serialized into the stream. +For this function will initialize an ``ucdrBuffer`` struct where a topic of ``topic_size`` size must be serialized. +Whether the necessary gap for writting a ``topic_size`` bytes into the stream, the returned value is ``true``, otherwise ``false``. The topic will be sent in the next ``run_session`` function. -NOTE: All `topic_size` bytes requested will be sent to the agent after a ``run_session`` call, no matter if the ``ucdrBuffer`` has been used or not. +NOTE: All ``topic_size`` bytes requested will be sent to the *Agent* after a ``run_session`` call, no matter if the ``ucdrBuffer`` has been used or not. :session: Session structure previously initialized. :stream_id: The output stream ID where the message will be written. -:datawriter_id: The DataWriter ID that will write the topic to the DDS World. -:mb_topic: A ``ucdrBuffer`` struct used to serialize the topic. +:datawriter_id: The `datawriter` ID that will write the topic to the DDS World. +:mb_topic: An ``ucdrBuffer`` struct used to serialize the topic. This struct points to a requested gap into the stream. :topic_size: The bytes that will be reserved in the stream. @@ -650,15 +703,13 @@ NOTE: All `topic_size` bytes requested will be sent to the agent after a ``run_s Discovery profile ``````````````````` -The discovery profile allows to discover agents in the network by UDP. -The reachable agents will respond to the discovery call sending information about them, as their ip and port. +The discovery profile allows to discover *Agents* in the network by UDP. +The reachable *Agents* will respond to the discovery call sending information about them, as their IP and port. There is two modes: multicast and unicast. -The discovery phase can be performed before the `uxr_create_session` call in order to determine the agent to connect with. -These functions are enabled when PROFILE_DISCOVERY is enabled in the ``client.config`` file. +The discovery phase can be performed before the `uxr_create_session` call in order to determine the *Agent* to connect with. +These functions are enabled when ``PROFILE_DISCOVERY`` is selected in the ``client.config`` file. The declaration of these functions can be found in ``uxr/client/profile/discovery/discovery.h``. -bool uxr_discovery_agents_multicast(uint32_t attemps, int period, uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* chosen); - ------ .. code-block:: c @@ -666,17 +717,17 @@ bool uxr_discovery_agents_multicast(uint32_t attemps, int period, uxrOnAgentFoun bool uxr_discovery_agents_multicast(uint32_t attempts, int period, uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* chosen); -Searches into the network using multicast ip "239.255.0.2" and port 7400 (default used by the agent) in order to discover agents. +Searches into the network using multicast IP "239.255.0.2" and port 7400 (default used by the *Agent*) in order to discover *Agents*. :attempts: The number of attempts to send the discovery message to the network. :period: How often will be sent the discovery message to the network. -:on_agent_func: The callback function that will be called when an agent was discovered. +:on_agent_func: The callback function that will be called when an *Agent* was discovered. The callback returns a boolean value. - A `true` means that the discovery rutine will be end and exit. - The current agent will be selected as *chosen*. - A `false` implies that the discovery rutine must to continue searching agents. + A `true` means that the discovery routine will be finished. + The current *Agent* will be selected as *chosen*. + A `false` implies that the discovery routine must continue searching *Agents*. :args: User arguments passed to the callback function. -:chosen: If the callback function was returned `true`, this value will contains the agent value of the callback. +:chosen: If the callback function was returned `true`, this value will contain the *Agent* value of the callback. ------ @@ -686,19 +737,19 @@ Searches into the network using multicast ip "239.255.0.2" and port 7400 (defaul uxrOnAgentFound on_agent_func, void* args, uxrAgentAddress* chosen, const uxrAgentAddress* agent_list, size_t agent_list_size); -Searches into the network using a list of unicast directions in order to discover agents. +Searches into the network using a list of unicast directions in order to discover *Agents*. :attempts: The number of attempts to send the discovery message to the network. :period: How often will be sent the discovery message to the network. -:on_agent_func: The callback function that will be called when an agent was discovered. +:on_agent_func: The callback function that will be called when an *Agent* is discovered. The callback returns a boolean value. - A ``true`` means that the discovery rutine will be end and exit. - The current agent will be selected as *chosen*. - A ``false`` implies that the discovery rutine must to continue searching agents. + A ``true`` means that the discovery routine will be finished. + The current *Agent* will be selected as *chosen*. + A ``false`` implies that the discovery routine must continue searching *Agents*. :args: User arguments passed to the callback function. -:chosen: If the callback function was returned ``true``, this value will contains the agent value of the callback. -:agent_list: The list of address where discover agent. - By default the agents will be listen at **port 7400** the discovery messages.. +:chosen: If the callback function was returned ``true``, this value will contain the *Agent* value of the callback. +:agent_list: The list of addresses where discover *Agent*. + By default the *Agents* will be listen at **port 7400** the discovery messages. :agent_list_size: The size of the ``agent_list``. ------ @@ -706,7 +757,7 @@ Searches into the network using a list of unicast directions in order to discove Topic serialization ``````````````````` Functions to serialize and deserialize topics. -These functions are generated automatically by `Micro XRCE-DDS Gen` utility over an idl file with a topic `TOPICTYPE`. +These functions are generated automatically by `Micro XRCE-DDS Gen` utility over an IDL file with a topic `TOPICTYPE`. The declaration of these function can be found in the generated file ``TOPICTYPE.h``. ------ @@ -715,10 +766,10 @@ The declaration of these function can be found in the generated file ``TOPICTYPE bool TOPICTYPE_serialize_topic(struct ucdrBuffer* writer, const TOPICTYPE* topic); -It serializes a topic into a ucdrBuffer. +Serializes a topic into an ``ucdrBuffer``. The returned value indicates if the serialization was successful. -:writer: A ucdrBuffer representing the buffer for the serialization. +:writer: An ``ucdrBuffer`` representing the buffer for the serialization. :topic: Struct to serialize. ------ @@ -727,10 +778,10 @@ The returned value indicates if the serialization was successful. bool TOPICTYPE_deserialize_topic(struct ucdrBuffer* reader, TOPICTYPE* topic); -It deserializes a topic from a ucdrBuffer. +Deserializes a topic from an ucdrBuffer. The returned value indicates if the serialization was successful. -:reader: A ucdrBuffer representing the buffer for the deserialization. +:reader: An ucdrBuffer representing the buffer for the deserialization. :topic: Struct where deserialize. ------ @@ -739,7 +790,7 @@ The returned value indicates if the serialization was successful. uint32_t TOPICTYPE_size_of_topic(const TOPICTYPE* topic, uint32_t size); -It counts the number of bytes that the topic will need in a `ucdrBuffer`. +Counts the number of bytes that the topic will need in an `ucdrBuffer`. :topic: Struct to count the size. :size: Number of bytes already written into the `ucdrBuffer`. @@ -759,11 +810,11 @@ The declaration of these functions can be found in ``uxr/client/core/session/str uxrStreamId uxr_stream_id(uint8_t index, uxrStreamType type, uxrStreamDirection direction); Creates an stream identifier. -This function does not create a new stream, only creates its identifier to be used in the `Client` API. +This function does not create a new stream, only creates its identifier to be used in the *Client* API. :index: Identifier of the stream, its value correspond to the creation order of the stream, different for each `type`. -:type: The type of the stream, it can be UXR_BEST_EFFORT_STREAM or UXR_RELIABLE_STREAM. -:direction: Represents the direccion of the stream, it can be UXR_INPUT_STREAM or MT_OUTPUT_STREAM. +:type: The type of the stream, it can be ``UXR_BEST_EFFORT_STREAM`` or ``UXR_RELIABLE_STREAM``. +:direction: Represents the direccion of the stream, it can be ``UXR_INPUT_STREAM`` or ``UXR_OUTPUT_STREAM``. ------ @@ -772,14 +823,14 @@ This function does not create a new stream, only creates its identifier to be us uxrStreamId uxr_stream_id_from_raw(uint8_t stream_id_raw, uxrStreamDirection direction); Creates an stream identifier. -This function does not create a new stream, only creates its identifier to be used in the `Client` API. +This function does not create a new stream, only creates its identifier to be used in the *Client* API. -:raw: identifier of the stream. +:stream_id_raw: Identifier of the stream. It goes from 0 to 255. 0 is for internal library use. 1 to 127, for best effort. 128 to 255, for reliable. -:direction: Represents the direccion of the stream, it can be UXR_INPUT_STREAM or MT_OUTPUT_STREAM. +:direction: Represents the direction of the stream, it can be ``UXR_INPUT_STREAM`` or ``MT_OUTPUT_STREAM``. ------ @@ -789,16 +840,10 @@ This function does not create a new stream, only creates its identifier to be us Creates a identifier for reference an entity. -:id: identifier of the object, different for each `type` - (Can be several ids with the same id if they have different types) +:id: Identifier of the object, different for each `type` + (can be several IDs with the same ID if they have different types). :type: The type of the entity. - It can be: - * UXR_PARTICIPANT_ID - * UXR_TOPIC_ID - * UXR_PUBLISHER_ID - * UXR_SUBSCRIBER_ID - * UXR_DATAWRITER_ID - * UXR_DATAREADER_ID + It can be: ``UXR_PARTICIPANT_ID``, ``UXR_TOPIC_ID``, ``UXR_PUBLISHER_ID``, ``UXR_SUBSCRIBER_ID``, ``UXR_DATAWRITER_ID`` or ``UXR_DATAREADER_ID``. ------ @@ -813,58 +858,46 @@ The common init transport functions follow the next nomenclature. .. code-block:: c - bool uxr_init_udp_transport(UDPTransport* transport, const char* ip, uint16_t port); + bool uxr_init_udp_transport(uxrUDPTransport* transport, uxrUDPPlatform* platform, const char* ip, uint16_t port); Initializes an UDP connection. :transport: The uninitialized structure used for managing the transport. - This structure must to be accesible during the connection. -:ip: Agent ip. -:port: Agent port. + This structure must to be accessible during the connection. +:platform: Structure which contains platform dependent members. +:ip: *Agent* IP. +:port: *Agent* port. ------ .. code-block:: c - bool uxr_init_tcp_transport(TCPTransport* transport, const char* ip, uint16_t port); + bool uxr_init_tcp_transport(uxrTCPTransport* transport, uxrTCPPlatform* platform, const char* ip, uint16_t port); Initializes a TCP connection. -If the TCP is used, the behaviour of best effort streams will be similiar to reliable streams in UDP. - -:transport: The uninitialized structure used for managing the transport. - This structure must to be accesible during the connection. -:ip: Agent ip. -:port: Agent port. - ------- - -.. code-block:: c - - bool uxr_init_serial_transport(SerialTransport* transport, const char* device, uint8_t remote_addr, uint8_t local_addr); - -Initializes a Serial connection using a device. +If the TCP is used, the behaviour of best effort streams will be similar to reliable streams in UDP. :transport: The uninitialized structure used for managing the transport. - This structure must to be accesible during the connection. -:device: Device used for the serial connection. -:remote_addr: Identifier of the agent in the serial connection. - By default, the agent identifier in a serial is 0. -:local_addr: Identifier of the client in the serial connection. + This structure must to be accessible during the connection. +:platform: Structure which contains platform dependent members. +:ip: *Agent* IP. +:port: *Agent* port. ------ .. code-block:: c - bool uxr_init_serial_transport_fd(SerialTransport* transport, const int fd, uint8_t remote_addr, uint8_t local_addr); + bool uxr_init_serial_transport(uxrSerialTransport* transport, uxrSerialPlatform* platform, const int fd, uint8_t remote_addr, uint8_t local_addr); Initializes a Serial connection using a file descriptor :transport: The uninitialized structure used for managing the transport. - This structure must to be accesible during the connection. + This structure must to be accessible during the connection. +:platform: Structure which contains platform dependent members. :fd: File descriptor of the serial connection. Usually, the fd comes from the ``open`` OS function. -:remote_addr: Identifier of the agent in the serial connection. - By default, the agent identifier in a serial is 0. -:local_addr: Identifier of the client in the serial connection. +:remote_addr: Identifier of the *Agent* in the serial connection. + By default, the *Agent* identifier in a serial is 0. +:local_addr: Identifier of the *Client* in the serial connection. ------ @@ -876,3 +909,19 @@ Closes a transport previously opened. `PROTOCOL` can be ``udp``, ``tcp`` or ``se :transport: The transport to close. +Creation Mode Table +################### + +The following table summarize the behaviour of the *Agent* under entity creation request. + +=========================== ================= ========== +**Creation flags** **Entity exists** **Result** +=========================== ================= ========== +Don't care NO Entity is created. +``0`` YES No action is taken, and ``UXR_STATUS_ERR_ALREADY_EXITS`` is returned. +``UXR_REPLACE`` YES Existing entity is deleted, requested entity is created and ``UXR_STATUS_OK`` is returned. +``UXR_REUSE`` YES | If entity matches no action is taken and ``UXR_STATUS_OK_MATCHED`` is returned. + | If entity does not match no action is taken and ``UXR_STATUS_ERR_MISMATCH`` is returned. +``UXR_REUSE | UXR_REPLACE`` YES | If entity matches no action is taken and ``UXR_STATUS_OK_MATCHED`` is returned. + | If entity does not match, exiting entity is deleted, requested entity is created and ``UXR_STATUS_OK`` is returned. +=========================== ================= ========== diff --git a/docs/conf.py b/docs/conf.py index 1052cb9d..903736d7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -49,7 +49,7 @@ # General information about the project. project = u'Micro XRCE-DDS' -copyright = u'2017, eProsima' +copyright = u'2018, eProsima' author = u'eProsima' # The version info for the project you're documenting, acts as replacement for @@ -59,7 +59,7 @@ # The short X.Y version. version = u'1.0.0' # The full version, including alpha/beta/rc tags. -release = u'1.0.0Beta2' +release = u'1.0.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/dependencies.rst b/docs/dependencies.rst index 4cbe9ca7..29208757 100644 --- a/docs/dependencies.rst +++ b/docs/dependencies.rst @@ -3,9 +3,9 @@ External dependencies Required dependences -------------------- -*Micro XRCE-DDS - Client* does not require external dependencies. +*Micro XRCE-DDS Client* does not require external dependencies. -*Micro XRCE-DDS - Agent* requires following packages to work: +*Micro XRCE-DDS Agent* requires the following packages to work: Fast RTPS *eProsima Fast RTPS* could be installed following the instructions: @@ -13,8 +13,8 @@ Fast RTPS Windows ~~~~~~~ -Microsoft Visual C++ 2013 or 2015 - *eProsima Micro XRCE-DDS* is supported on Windows over Microsoft Visual C++ 2013 or 2015 framework. +Microsoft Visual C++ 2015 or 2017 + *eProsima Micro XRCE-DDS* is supported on Windows over Microsoft Visual C++ 2015 or 2017 framework. Additional Dependencies ----------------------- diff --git a/docs/deployment.rst b/docs/deployment.rst index c2d49789..36012a21 100644 --- a/docs/deployment.rst +++ b/docs/deployment.rst @@ -3,20 +3,20 @@ Deployment example ================== -This part will show how to deploy a system using *Micro XRCE-DDS* in a real enviroment. +This part will show how to deploy a system using *Micro XRCE-DDS* in a real environment. An example of this can be found into ``examples/Deployment`` folder. Previous tutorials are based in `all in one` examples, that is, examples that create entities, publish or subscribe and then delete the resources. One possible real purpose of this, consists in differentiate the logic of `creating entities` and the actions of `publishing and subscribing`. -This can be done creating two differents clients. -One for configurating the entities in the agent, and run possibly once, only for creating the entities at configuration time. -And other/s, that logs in the same session as the configure client (sharing the entities) and only publishes or subscribes data. +This can be done creating two differents *Clients*. +One in charge of configure the entities in the *Agent*, and run possibly once, only for creating the entities at configuration time. +And other/s that logs in the same session as the configure *Client* (sharing the entities) and only publishes or subscribes data. -This way allows to create easy clients in production only with the purpose of send and receive data. -Related to it, exists the concept of `profile` that allows to build the client library only with the behavior chosen (only publish or only subscribe, for example). +This way allows to easily create *Clients* in a real scenario only with the purpose of send and receive data. +Related to it, the concept of `profile` allows to build the *Client* library only with the chosen behavior (only publish or only subscribe, for example). See :ref:`micro_xrce_dds_client_label` for more information about this. -Next diagram shows an example about how to configure the enviroment using a `configurator client`. +Next diagram shows an example about how to configure the environment using a `configurator client`. Initial state ------------- @@ -25,7 +25,7 @@ Initial state :width: 600 px :align: center -The enviroment contains two agents (is perfectly possible to use only one agent too), and two clients, one for publishing and other subscribing. +The environment contains two *Agents* (is perfectly possible to use only one *Agent* too), and two *Clients*, one for publishing and another for subscribing. Configurate the publisher @@ -35,11 +35,11 @@ Configurate the publisher :width: 600 px :align: center -In this state a `configurator client` is connected to the agent `A` with the `client key` that will be used by the future `publisher client` (0xAABBCCDD). -Once a session is logged in, the `configurator client` creates all necesary entities for the `publisher client`. +In this state a `configurator client` is connected to the *Agent* `A` with the `client key` that will be used by the future `publisher client` (0xAABBCCDD). +Once a session is logged in, the `configurator client` creates all the necessary entities for the `publisher client`. This implies the creation of `participant`, `topic`, `publisher`, and `datawriter` entities. These entities have a representation as DDS entities, and can be reached now from the DDS world. -That implies that a possible `subscriber DDS entity` could be already listening topics if it match with a `publisher DDS entity` through `DDS` world. +That implies that a possible `subscriber DDS entity` could already be listening topics if it matches with a `publisher DDS entity` through `DDS` world. Publish ------- @@ -47,10 +47,10 @@ Publish :width: 600 px :align: center -Then, the `publisher client` is connected to the agent `A`. -This client logs in session with its client key (0xAABBCCDD). +Then, the `publisher client` is connected to the *Agent* `A`. +This *Client* logs in session with its *Client* key (0xAABBCCDD). At that moment, it can use all entities created related to this `client key`. -Because all entities that it uses were created successful by the `configurator client`, the `publisher client` can inmediately publish to `DDS`. +Because all entities that it used were successfully created by the `configurator client`, the `publisher client` can immediately publish to `DDS`. Configurate the subscriber @@ -60,7 +60,7 @@ Configurate the subscriber :width: 600 px :align: center -Again, the `configurator client` connects and logs in, this time to agent `B`, now with the subscriber's key (0x11223344). +Again, the `configurator client` connects and logs in, this time to *Agent* `B`, now with the subscriber's key (0x11223344). In this case, the entities that the `configurator client` creates are a `participant`, a `topic`, a `subscriber`, and a `datareader`. The entities created by the `configuraton client` will be available until the session is deleted. @@ -71,7 +71,7 @@ Subscriber :width: 600 px :align: center -Once the subscriber is configured, the `subscriber client` logs in the agent `B`. +Once the subscriber is configured, the `subscriber client` logs in the *Agent* `B`. As all their entities have been created previously, so it only need to configure the read after log in. Once the data request message has been sent, the subscriber will receive the topics from the publisher through `DDS` world. diff --git a/docs/entities.rst b/docs/entities.rst index 8884ccc0..4199b47c 100644 --- a/docs/entities.rst +++ b/docs/entities.rst @@ -7,8 +7,8 @@ The protocol under `Micro XRCE-DDS` (XRCE), defines entities that have a direct The entities manage the communication between `Micro XRCE-DDS Client` and the DDS Global Data Space. Entities are stored in the `Micro XRCE-DDS Agent` and the `Micro XRCE-DDS Client` can create, use and destroy these entities. -The entities are uniquely identified by an ID called `Object ID`. `Object ID` is the way a `Client` refers to them inside an Agent. -In most of the `Client` request operations is necessary to specify an ID referring to one of the `Client` entities stored in the `Agent`. +The entities are uniquely identified by an ID called `Object ID`. The `Object ID` is the way a *Client* refers to them inside an *Agent*. +In most of the *Client* request operations is necessary to specify an ID referring to one of the *Client* entities stored in the *Agent*. Type of Entities ---------------- diff --git a/docs/gen.rst b/docs/gen.rst index 1ef69e57..4925ee41 100644 --- a/docs/gen.rst +++ b/docs/gen.rst @@ -7,7 +7,7 @@ Micro XRCE-DDS Gen This tool is able to generate from a given IDL specification file, the C struct associated with the Topic, as well as, the serialization and deserialization methods. -Also, it has the possibility of generate a sample demo that works with proposed topic. +Also, it has the possibility to generate a sample demo that works with the proposed topic. As an example of the powerful of this tool, the following shows the source code generated from the ShapeDemo IDL file. :: @@ -64,18 +64,18 @@ it will generate the following header file and its corresponding source: #endif // _ShapeType_H_ -*Micro XRCE-DDS Gen* is also able to generate both *publisher* and *subscriber* source code examples related with the topic speficified in the IDL file adding the flag ``-example``: :: +*Micro XRCE-DDS Gen* is also able to generate both *publisher* and *subscriber* source code examples, related with the topic specified in the IDL file, by adding the flag ``-example``: :: $ microxrceddsgen -example -In order to use these examples, the client library must be compiled with the ``WRITE_ACCESS_PROFILE`` option for the *publisher* +In order to use these examples, the *Client* library must be compiled with the ``WRITE_ACCESS_PROFILE`` option for the *publisher* and the ``READ_ACCESS_PROFILE`` option for the *subscriber*. Installation ------------ -For use *Micro XRCE-DDS Gen* you have to follow the next steps: +In order to use *Micro XRCE-DDS Gen*, it is needed to follow the next steps: 1. Install its dependencies: diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 5a4f1117..8f32b742 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -39,7 +39,7 @@ Also, we will specify the max buffer for the streams and its historical associat #define STREAM_HISTORY 8 #define BUFFER_SIZE UXR_CONFIG_UDP_TRANSPORT_MTU * STREAM_HISTORY -Before create a Session we need to indicate the transport to use (the agent must be configured for listening from udp at port 2018). +Before create a Session we need to indicate the transport to use (the *Agent* must be configured for listening from UDP at port 2018). .. code-block:: C @@ -51,7 +51,7 @@ Before create a Session we need to indicate the transport to use (the agent must return 1; } -Next, we will create a session that allow us interact with the agent: +Next, we will create a session that allows us interact with the *Agent*: .. code-block:: C @@ -64,10 +64,10 @@ Next, we will create a session that allow us interact with the agent: return 1; } -The first function ``uxr_init_session`` initializes the ``Session`` structure with the transport and the `Client Key` (the session identifier for an agent). -The ``uxr_set_topic_callback`` function is for registering the function ``on_topic`` which has been called when the `Client` receive a topic. -Once the session has been initialized, we can send the first message for login the client in agent side: ``uxr_create_session``. -This function will try to connect with the agent by ``CONFIG_MAX_SESSION_CONNECTION_ATTEMPTS`` attempts (the value can be configurable at ``client.config``). +The first function ``uxr_init_session`` initializes the ``session`` structure with the transport and the `Client Key` (the session identifier for an *Agent*). +The ``uxr_set_topic_callback`` function is for registering the function ``on_topic`` which will be called when the `Client` receive a topic. +Once the session has been initialized, we can send the first message for login the `Client` in the *Agent* side: ``uxr_create_session``. +This function will try to connect with the *Agent* by ``CONFIG_MAX_SESSION_CONNECTION_ATTEMPTS`` attempts (configurable at ``client.config``). Optionally, we also could add a status callback with the function ``uxr_set_status_callback``, but for the purpose of this example we do not need it. @@ -82,14 +82,14 @@ In this case, we will use two, both reliables, for input and output. uint8_t input_reliable_stream_buffer[BUFFER_SIZE]; uxrStreamId reliable_in = uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY); -In order to publish and/or subscribe a topic, we need to create a hierarchy of XRCE entities in the agent side. -These entities will be created from the client. +In order to publish and/or subscribe a topic, we need to create a hierarchy of XRCE entities in the *Agent* side. +These entities will be created from the *Client*. .. image:: images/entities_hierarchy.svg Setup a Participant ^^^^^^^^^^^^^^^^^^^ -For establishing DDS communication we need to create a `Participant` entity for the `Client` in the `Agent`. +For establishing DDS communication we need to create a `Participant` entity for the `Client` in the *Agent*. We can do this calling *Create participant* operation: .. code-block:: C @@ -106,11 +106,11 @@ We can do this calling *Create participant* operation: In any `XRCE Operation` that creates an entity, an `Object ID` is necessary. It is used to represent and manage the entity in the *Client* side. -In this case we will create the entity by its XML description, but also could be done by a reference of the entity in the agent. +In this case we will create the entity by its XML description, but also could be done by a reference of the entity in the *Agent*. Each operation, returns a `Request ID`. This identifier of the operation can be used later for associating the status with the operation. In this case, the operation has been written into the stream ``reliable_out``. -Later, in the ``run_session`` function, the data written in the stream will be sent to the agent. +Later, in the ``run_session`` function, the data written in the stream will be sent to the *Agent*. Creating topics ^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ Once the `Participant` has been created, we can use `Create topic` operation for As any other XRCE Operation used to create an entity, an Object ID must be specified to represent the entity. The ``participant_id`` is the participant where the Topic will be registered. -In order to determine which topic will be used, an XML is sent to the agent for creating and defining the Topic in the DDS Global Data Space. +In order to determine which topic will be used, an XML is sent to the *Agent* for creating and defining the Topic in the DDS Global Data Space. That definition consists of a name and a type. Publishers & Subscribers @@ -147,7 +147,7 @@ We create a publisher or subscriber on a participant entity, so it is necessary const char* subscriber_xml = ""; uint16_t subscriber_req = uxr_buffer_create_subscriber_xml(&session, reliable_out, subscriber_id, participant_id, subscriber_xml, UXR_REPLACE); -The `Publisher` and `Subscriber` xml information is given when the `DataWriter` and `DataReader` be created. +The `Publisher` and `Subscriber` XML information is given when the `DataWriter` and `DataReader` are created. DataWriters & DataReaders ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -190,8 +190,7 @@ an status is sent from the *Agent* to the *Client* indicating what happened. For `Create session` or `Detele session` operations the status value is stored into the ``session.info.last_request_status``. For the rest of the operations, the status are sent to the input reliable stream ``0x80``, that is, the first input reliable stream created, with index 0. -The different status values that the agent can send to the client are the following: -(You can see the definitions in ``uxr/client/core/sesssion/session_info.h`` file) +The different status values that the *Agent* can send to the *Client* are the following (defined in ``uxr/client/core/session/session_info.h``): .. code-block:: C @@ -220,7 +219,7 @@ The status can be handle by the ``on_status_callback`` callback (configured in ` } The ``run_session`` functions are the main functions of the `Micro RTP Client` library. -They performs serveral tasks: send the stream data to the agent, listen data from the agent, call callbacks, and manage the reliable connection. +They performs serveral tasks: send the stream data to the *Agent*, listen data from the *Agent*, call callbacks, and manage the reliable connection. There are five variations of ``run_session`` function: - ``uxr_run_session_time`` - ``uxr_run_session_until_timeout`` @@ -253,7 +252,7 @@ The function ``uxr_prepare_output_stream`` requests a writing for a topic of ``t with a ``datawriter_id`` (correspond to the data writer entity used for sending the data in the `DDS World`). If the stream is available and the topic fits in it, the function will initialize the ``ucdrBuffer`` structure ``mb``. Once the ``ucdrBuffer`` is prepared, the topic can be serialized into it. -We are careless about ``uxr_prepare_output_stream`` return value because the serialization only will occur if the ``ucdrBuffer` is valid`` +We are careless about ``uxr_prepare_output_stream`` return value because the serialization only will occur if the ``ucdrBuffer`` is valid. After the write function, as happened with the creation of entities, the topic has been serialized into the buffer but it has not been sent yet. To send the topic is necessary call to a ``run_session`` function. @@ -262,8 +261,8 @@ In this case, we call to ``uxr_run_session_until_confirmed_delivery`` that will Read Data ^^^^^^^^^ Once we have created a valid `DataReader` entity, we can read data from the DDS Global Data Space using the read operation. -This operation configures how the agent will send the data to the client. -Current implementation sends one topic to the client for each read data operation of the client. +This operation configures how the *Agent* will send the data to the *Client*. +Current implementation sends one topic to the *Client* for each read data operation of the *Client*. .. code-block:: C @@ -272,12 +271,12 @@ Current implementation sends one topic to the client for each read data operatio uint16_t read_data_req = uxr_buffer_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control); -In order to configure how the agent will send the topic, we must set the input stream. In this case, we use the input reliable stream previously defined. +In order to configure how the *Agent* will send the topic, we must set the input stream. In this case, we use the input reliable stream previously defined. ``datareader_id`` corresponds with the `DataDeader` entity used for receiving the data. -The ``delivery_control`` parameter is option, and allow to specify how the data will be deliverd to the client. -For the example purpose, we set it as `unlimited`, so any number HelloWorld topic will be delivered to the client. +The ``delivery_control`` parameter is optional, and allows to specify how the data will be delivered to the *Client*. +For the example purpose, we set it as `unlimited`, so any number HelloWorld topic will be delivered to the *Client*. -The ``run_session`` function will call the topic callback each time a topic will be received from the agent. +The ``run_session`` function will call the topic callback each time a topic will be received from the *Agent*. .. code-block:: C @@ -296,7 +295,7 @@ The ``args`` argument correspond to user free data, that has been given at `uxr_ Closing the Client ^^^^^^^^^^^^^^^^^^ To close a `Client`, we must perform two steps. -First, we need to tell the agent that the session is no longer available. +First, we need to tell the *Agent* that the session is no longer available. This is done sending the next message: .. code-block:: C diff --git a/docs/images/xrcedds_architecture.png b/docs/images/xrcedds_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..1990a4011956f093715da81a555a90e78e814053 GIT binary patch literal 43924 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 -
Micro XRCE-DDS Agent
[Not supported by viewer]
DDS-XRCE
[Not supported by viewer]
RTPS
RTPS
Low Resources Device
Low Resources Device
Micro XRCE-DDS Client
<b>Micro XRCE-DDS Client</b>
DDS-XRCE
[Not supported by viewer]
Low Resources Device
Low Resources Device
Micro XRCE-DDS Client
<b>Micro XRCE-DDS Client</b>
\ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 58890f3a..cfc23bd2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,7 +7,7 @@ eProsima Micro XRCE-DDS ----------------------- *eProsima Micro XRCE-DDS* is a software solution which allows to communicate eXtremely Resource Constrained Environments (XRCEs) with an existing DDS network. -This implementation complies with the specification proposal, "eXtremely Resource Constrained Environments DDS (DDS-XRCE)" submitted to the Object Management Group (OMG) consortium. +This implementation complies with the specification proposal, "DDS for eXtremely Resource Constrained Environments" submitted to the Object Management Group (OMG) consortium. *Micro XRCE-DDS* implements a client-server protocol to enable resource-constrained devices (clients) to take part in DDS communications. *Micro XRCE-DDS Agent* (server) makes possible this communication acting on behalf of the *Micro XRCE-DDS Clients* @@ -15,7 +15,7 @@ and enables them to take part as DDS publishers and/or subscribers in the DDS Gl *Micro XRCE-DDS* provides both, a plug and play *Micro XRCE-DDS Agent* and an API layer which allows you to implement your *Micro XRCE-DDS Clients*. -.. image:: images/xrcedds_architecture.svg +.. image:: images/xrcedds_architecture.png Main features ~~~~~~~~~~~~~ @@ -71,10 +71,10 @@ To test *Micro XRCE-DDS* in your computer, you can follow the :ref:`quickstart_l This page shows how to create a simple publisher as a XRCE client that send topics into the DDS World. Additionally, there is an interactive example called :ref:`shapes_demo_label` that allow you to create entities and -to send/receive topics by the instructions given by command line. +to send/receive topics by instructions given by command line. This example is useful to understand how XRCE protocol works along to the DDS World. -To create your own client, you can follow the the instructions of :ref:`getting_started_label` page. +To create your own client, you can follow the instructions of :ref:`getting_started_label` page. This is a tutorial that describe briefly how *Micro XRCE-DDS* API is and how it works. To know more about *Micro XRCE-DDS*, you can read the corresponding parts to the :ref:`micro_xrce_dds_client_label` or the :ref:`micro_xrce_dds_agent_label`. diff --git a/docs/installation.rst b/docs/installation.rst index e628796e..17e88bb1 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -71,13 +71,13 @@ On Windows first select the Visual Studio version: :: $ cmake --build . --target install If you want to install the *Micro XRCE-DDS Client* examples you can add ``-DEPROSIMA_BUILD_EXAMPLES=ON`` to the CMake command line options. -This flag will enable the compilation of the examples when the project it is compiled. +This flag will enable the compilation of the examples when the project is compiled. There are several CMake definitions for configuring the build of the client library at compile time. You can found them in :ref:`micro_xrce_dds_client_label` page under `Configuration` section. Compiling an app with the Client library ---------------------------------------- -For building your client program you need to build against the following libs: :: +For building your Client app you need to build against the following libs: :: gcc -lmicrocdr -lmicroxrcedds_client diff --git a/docs/introduction.rst b/docs/introduction.rst index 769c0492..6112cd08 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -8,24 +8,24 @@ DDS-XRCE protocol `Micro XRCE-DDS` implements `DDS-XRCE protocol `_ specified in the `DDS for eXtremely Resource Constrained Environments` proposal submitted to the `Object Management Group (OMG)` consortium. -This protocol allows to communicate resource constrained clients with a larger `DDS (Data Distribution Service)` network. +This protocol allows to communicate resource constrained devices with a larger `DDS (Data Distribution Service)` network. This communication is done using a client-server architecture, where the server (Agent) acts as an intermediary between clients and `DDS Global Data Space`. `DDS-XRCE protocol` defines a wire protocol between XRCE Agents and XRCE Clients. -This message exchanged revolves around operations and their responses. +The messages exchanged revolve around operations and their responses. XRCE Clients ask the XRCE Agents to run operations and the XRCE Agents reply with the result of those requested operations. Making use of those operations, XRCE Clients are able to create the DDS entities hierarchy necessary to publish and/or receive data from DDS. DDS entities are created and stored on the XRCE Agent side so the XRCE Clients can reuse them at will. -`Micro XRCE-DDS` implements the DDS-XRCE protocol using a *Micro XRCE-DDS Agent* as server and providing a C API for developing XRCE Clients. +`Micro XRCE-DDS` implements the DDS-XRCE protocol using a *Micro XRCE-DDS Agent* as server and providing a C API for developing XRCE Clients applications. `Micro XRCE-DDS Agent` uses `Fast RTPS` to reach the DDS Global Data Space. -.. image:: images/xrcedds_architecture.svg +.. image:: images/xrcedds_architecture.png Fast RTPS ````````` -*eProsima Fast RTPS* is a C++ implementation of the `XRCE-DDS (Real-Time Publish-Subscribe)` protocol, +*eProsima Fast RTPS* is a C++ implementation of the `RTPS (Real-Time Publish-Subscribe)` protocol, which provides publisher-subscriber communications over unreliable transports such as UDP, as defined and maintained by the `OMG` consortium. XRCE-DDS is also the wire interoperability protocol defined for the `DDS` standard, again by the `OMG`. @@ -35,8 +35,7 @@ For deeper information please refer to the official documentation: `eProsima Fas Operations and entities ----------------------- *Micro XRCE-DDS* communication between XRCE Client and XRCE Agent is based upon :ref:`operations_label` and responses. -Clients request operations to the Agent. -The Agent will process the received operations and generate responses with the result of these operations. +Clients request operations to the Agent which will generate responses with the result of these operations. Clients may process the responses to know how an operations request has ended in the Agent. *Micro XRCE-DDS Client* can request a variety of operations to the *Micro XRCE-DDS Agent*: @@ -45,14 +44,14 @@ Clients may process the responses to know how an operations request has ended in * Create and delete entities. * Write and read Data. -First of all the `Agent` must know about any `Client`. +First of all, the `Agent` must know about any `Client`. This is done by sending a `Create session` operation from the `Client` to the `Agent`, which will register the `Client`. If you do not register the session, all the operations sending to the `Agent` will be refused. Once registered, the `Client` can request operations to the `Agent`. The `Client` can create and query entities using operations. The communication with `DDS` is handled by `Agent` using :ref:`entities_label`. -`Create entity` Operation is the request you use to create entities on the `Agent`. +`Create entity` Operation is the request you use to create entities in the `Agent`. Each one of these entities corresponds with a `Fast RTPS` object. The entities you can create are: @@ -73,7 +72,7 @@ Also, if you want to log out a `Client` session from the `Agent`, you can use th Topic Type ---------- The data sent by the `Client` to the `DDS Global Data Space` uses the same principles as in `Fast RTPS`. -The `Interface Definition Language (IDL) `_ is used to define the type and must be known by the client. +The `Interface Definition Language (IDL) `_ is used to define the type and must be known by the `Client`. Having the type defined as `IDL` we provide the :ref:`microxrceddsgen_label` tool. This tool is able to generate a compatible type that the *Micro XRCE-DDS Client* can use to send and receive. The type should match the one used on the DDS Side. diff --git a/docs/notes.rst b/docs/notes.rst index a4965ca8..7640ee2e 100644 --- a/docs/notes.rst +++ b/docs/notes.rst @@ -3,12 +3,12 @@ Version 1.0.0 This release includes the following features: -* Extended C topic code generation tool (strings, sequences, n-dimensional arrays). +* Extended C topic code generation tool (strings, sequences and n-dimensional arrays). * Discovery profile. * Native write access profile (without using Micro XRCE-DDS Gen) -* Creation and configuration by xml. +* Creation and configuration by XML. * Creation by reference. -* Added reuse flag at create entities. +* Added `REUSE` flag at create entities. * Added prefix to functions. * Transport stack modification. * More tests. @@ -23,8 +23,8 @@ Version 1.0.0Beta2 ~~~~~~~~~~~~~~~~~~ This release includes the following features: -* Reability. -* Stream concept (best effort, reliable). +* Reliability. +* Stream concept (best-effort, reliable). * Multiples streams of same type. * Configurable data delivery control. * C Topic example code generation tool. diff --git a/docs/operations.rst b/docs/operations.rst index 8e898bde..ad2f5813 100644 --- a/docs/operations.rst +++ b/docs/operations.rst @@ -3,13 +3,13 @@ Operations ========== Operations are the possible actions your *Micro XRCE-DDS Client* can ask to the *Micro XRCE-DDS Agent*. -Operations revolve around `entities`. :ref:`entities_label`. +Operations revolve around :ref:`entities_label`. *Micro XRCE-DDS Agent* will respond to all the requests with the status of the operation. Types ----- `Create session` - `Create session` asks the agent to register a session. + `Create session` asks the *Agent* to register a session. This is the first operation that you must request. If this operation fails or you don't request it, any of the following operations will not work. This operation will create the session corresponding to the *Client-Agent* connection. @@ -24,18 +24,15 @@ Types Each `Create entity` operation are related to an ID for its management. `Delete entity` - Analogous to create entities a session can to drop the entities on the *Agent*. + Analogous to create entities a session can drop the entities on the *Agent*. To drop an entity you need to request a deletion of the entity to the *Agent* using the entity ID. `Request Data` - This operation configures how do you want to receive data, and the Agent will deliver it from the DDS to your *Client*. + This operation configures how do you want to receive data, and the *Agent* will deliver it from the DDS to your *Client*. This data will be receive asynchronously, in accordance with the data delivery control setted in this operation. - Reading data is done using a DataReader entity. + Reading data is done using a `DataReader` entity. About XML Representation ------------------------ -Creating a Topic, a DataWriter or a DataReader needs to be done using DDS XML configuration of the object to create. +`Participats`, `Topics`, `DataWriters` and `DataReaders` creation needs to be done using DDS XML configuration of the object to create. That XML configuration follows the same rules as in *Fast RTPS*. - -Creating a Participant is done using the ``default participant`` profile found already preconfigured in the agent. -Yo can change the Participant configuration changing the ``DEFAULT_FASTRTPS_PROFILES.xml`` file found along with de *Micro XRCE-DDS Agent* installation. diff --git a/docs/optimization.rst b/docs/optimization.rst index 78c1311c..8df7764f 100644 --- a/docs/optimization.rst +++ b/docs/optimization.rst @@ -9,21 +9,24 @@ In order to manage the executable code size, the library can be compiled enablin To add or remove a profile from the library, edit the ``client.config`` file. More information can be found at: :ref:`micro_xrce_dds_client_label`. +NOTE: If you are compiling your app with *gcc*, its highly recommended compile it with the linker flag: ``-Wl,--gc-sections``. +This will remove the code that your app does not use from the final executable. + Runtime size ------------ -The client is dynamic memory free and static memory free. +The *Client* is dynamic memory free and static memory free. This implies that all memory charge depends only on how the stack grows during the execution. To control the stack, there are some values that can be modified and that impact to a large degree: Stream buffers ~~~~~~~~~~~~~~ -1. Make sure you defined only the streams that will be used. - You can define a maximun `127` best effort streams and `128` reliable streams, - but for the majory of purposes, only one stream of either best effort or reliable can be used. +1. Make sure you define only the streams that will be used. + You can define a maximum `127` best-effort streams and `128` reliable streams, + but for the majority of purposes, only one stream of either best effort or reliable can be used. 2. The history of a reliable streams is used for recovering from lost messages and speeding up the communication. - For output streams, more history value will allow writing and send more messages without wait confirmation. - If a history of an output stream is full (no messages were still confirmed by the agent), no more messages can be storaged into the stream. + For output streams, more history value will allow to write and send more messages without wait confirmation. + If a history of an output stream is full (no messages were still confirmed by the *Agent*), no more messages can be storaged into the stream. For input streams, the history is used for recovering faster when the messages are lost using less extra band-width. If your connection is highly reliable and to save memory is a priority, a reduced history can be used. diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 73d44277..a8db2e86 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -205,8 +205,15 @@ The code of the *SubscriberHelloWorldClient* is the following: { if(args >= 2 && (0 == strcmp("-h", argv[1]) || 0 == strcmp("--help", argv[1]) || 0 == atoi(argv[1]))) { - printf("usage: program [-h | --help | ]\n"); - return 0; + (void) session; (void) object_id; (void) request_id; (void) stream_id; + + HelloWorld topic; + HelloWorld_deserialize_topic(mb, &topic); + + printf("Received topic: %s, id: %i\n", topic.message, topic.index); + + uint32_t* count_ptr = (uint32_t*) args; + (*count_ptr)++; } uint32_t count = 0; @@ -319,7 +326,7 @@ To learn more about DDS and Fast RTPS: `eProsima Fast RTPS `_ is an interactive example for testing how `Fast RTPS` working in the `DDS Global Data Space`. -Because the aim of `Micro XRCE-DDS` is connect a `XRCE Client` to the `DDS World`, in this example we will create a client which will interact with the `Shapes Demo`. +Because the aim of `Micro XRCE-DDS` is connect an `XRCE Client` to the `DDS World`, in this example we will create a *Client* which will interact with the `Shapes Demo`. It can be found at `examples/uxr/client/ShapeDemoClient` inside of the installation directory. -This interactive client waits for user input indicating commands to execute. +This interactive *Client* waits for user input indicating commands to execute. The available commands are the following: @@ -44,7 +44,7 @@ tree, entity_tree : h, help: Shows this message. -For example, to create a publisher client that sends an square Topic in reliable mode, you need to run the following commands in order: :: +For example, to create a publisher *Client* that sends an square Topic in reliable mode, you need to run the following commands: :: > create_session > create_participant 1 @@ -53,9 +53,9 @@ For example, to create a publisher client that sends an square Topic in reliable > create_datawriter 1 1 > write_data 1 128 200 200 40 BLUE -This client will publish a topic in reliable mode that will have color BLUE, x coordinate 200, y coordinate 200, size 40. +This *Client* will publish a topic in reliable mode that will have color BLUE, x coordinate 200, y coordinate 200 and size 40. -In case of a subscriber client that receives square topics in a reliable mode, run the following: :: +In case of a subscriber *Client* that receives square topics in a reliable mode, run the following: :: > create_session > create_participant 1 @@ -64,7 +64,7 @@ In case of a subscriber client that receives square topics in a reliable mode, r > create_datareader 1 1 > request_data 1 128 5 -This client will received 10 topics in reliable mode. +This *Client* will received 5 topics in reliable mode. To create the entities tree easily, you can run the command ``entity_tree ``. For example, the following command creates the necessary entities for publishing and subscribing data with id `3`: :: @@ -79,9 +79,9 @@ For example, the following command creates the necessary entities for publishing To modify the output default stream, you can change it with `stream `. - > stream 1 - The maximun available streams corresponds with the ``CONFIG_MAX_OUTPUT_BEST_EFFORT_STREAMS`` and ``CONFIG_MAX_OUTPUT_RELIABLE_STREAMS`` properties configurable in ``client.config`` file. + > stream 1 + Now the messages will be send in best effort mode. From b3a48ca54582987471796b392cea694b7e32c2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Berm=C3=BAdez=20Ortega?= <34604561+julianbermudez@users.noreply.github.com> Date: Tue, 6 Nov 2018 15:48:57 +0100 Subject: [PATCH 16/16] Refs #3599. Added Fast RTPS version note. (#20) --- docs/dependencies.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/dependencies.rst b/docs/dependencies.rst index 29208757..c7168fdc 100644 --- a/docs/dependencies.rst +++ b/docs/dependencies.rst @@ -11,6 +11,8 @@ Fast RTPS *eProsima Fast RTPS* could be installed following the instructions: `eProsima Fast RTPS installation guide `_. +NOTE: *Micro XRCE-DDS Agent* is currently working under Fast RTPS develop branch until new Fast RTPS v1.7.0 Release is launched. + Windows ~~~~~~~ Microsoft Visual C++ 2015 or 2017