eProsima / Micro-XRCE-DDS

An XRCE DDS implementation. Looking for commercial support? Contact info@eprosima.com
Apache License 2.0
156 stars 17 forks source link

One session one publisher and two subscribers #86

Closed vibnwis closed 3 years ago

vibnwis commented 3 years ago

Hi teams,

It would very much appreciate if you share some thoughts about what went wrong here. I have five clients namely Master, Health_inventory, uclient_AA, uclient_BB, and uclient_CC. However, the main issues encountered are, in each uclient_AA, uclient_BB, and uclient_CC, it subscribe to Master and one of the other three uclients. Since each uclient_AA subscribes to two two-topics, I have the code as follow, not the full source. I only show the master-related source. However, they all do not work.

Something I need your clarification are:

  1. To subscribe to two publishers, does it need to have two callbacks? one for each publisher. See the code below, I have on_mas_topic() and on_topic().
  2. How does the code look like, for uxr_buffer_request_data for subscribing to two topics? see the code below. I have two uxr_buffer_request_data().

Nonetheless, the three uClients do not get any messages from any publishers. Appreciate your comments.

== callback code ==

void on_mas_topic(
        uxrSession* session,
        uxrObjectId object_id,
        uint16_t request_id,
        uxrStreamId stream_id,
        struct ucdrBuffer* ub,
        uint16_t length,
        void* args)
{
    (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) length;

    msbot_master topic;
    msbot_master_deserialize_topic(ub, &topic);

    printf("Received master topic: %s, id: %i\n", topic.message, topic.index);

    uint32_t* count_ptr = (uint32_t*) args;
    (*count_ptr)++;
}

void on_topic(
        uxrSession* session,
        uxrObjectId object_id,
        uint16_t request_id,
        uxrStreamId stream_id,
        struct ucdrBuffer* ub,
        uint16_t length,
        void* args)
{
    (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) length;

    HelloWorld topic;
    HelloWorld_deserialize_topic(ub, &topic);

    char key[20];
    snprintf(key, 20, "0x%X%X%X%X", session->info.key[0], session->info.key[1], session->info.key[2],
            session->info.key[3]);
    printf("Session %s: %s (%i)\n", key, topic.message, topic.index);
}
 --------------------------------
   uxr_set_topic_callback(&session, on_topic, NULL);
    uxr_set_topic_callback(&session, on_mas_topic, &count);
---------------------------------
 //---master topic---
    uxrObjectId mas_topic_id = uxr_object_id(0x01, UXR_TOPIC_ID);     //master topic
    const char* mas_topic_xml = "<dds>"
            "<topic>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</dds>";

   uint16_t mas_topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, mas_topic_id, participant_id, mas_topic_xml,
                    UXR_REPLACE);

    uxrObjectId mas_subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID);
    const char* mas_subscriber_xml = "";
    uint16_t mas_subscriber_req = uxr_buffer_create_subscriber_xml(&session, reliable_out, mas_subscriber_id, participant_id,
                    mas_topic_xml, UXR_REPLACE);

    uxrObjectId mas_datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID);
    const char* mas_datareader_xml = "<dds>"
            "<data_reader>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</data_reader>"
            "</dds>";

    uint16_t mas_datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, mas_datareader_id, mas_subscriber_id,
                    mas_datareader_xml, UXR_REPLACE);

    //---master-topic ---
-----------------------------

    uint16_t requests[] = {
        participant_req, mas_topic_req, mas_subscriber_req, mas_datareader_req, requester_req, topic_req_1_1, topic_req_1_2, publisher_req, datawriter_req, subscriber_req,
        datareader_req
    };

   // Request replies
    uxrDeliveryControl delivery_control = {
        0
    };
    delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED;
    uint16_t read_data_req = uxr_buffer_request_data(&session, reliable_out, requester_id, reliable_in,
                    &delivery_control);

    uint16_t read_data_req_topic = uxr_buffer_request_data(&session, reliable_out, datareader_id, reliable_in,
                    &delivery_control);

    uint16_t read_data_req_mas_topic_ = uxr_buffer_request_data(&session, reliable_out, mas_datareader_id, reliable_in,
                    &delivery_control);

   time_t t;

=====================================================

vibnwis commented 3 years ago

For full source code, see attached. Thank you

// 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.

/*
How to know which kind of Topic has been received?
To know which kind of Topic has been received, we can use the object_id parameter or
the request_id. The id of the object_id corresponds to the DataReader that has read
the Topic, so it can be useful to discretize among different topics.
*/
#include "HelloWorld.h"
#include "msbot_master.h"

#include <uxr/client/client.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdbool.h>
#include <time.h>

#define STREAM_HISTORY  8
#define BUFFER_SIZE     UXR_CONFIG_UDP_TRANSPORT_MTU* STREAM_HISTORY

char partname[] = "ABCD";
char localpartname[] = "ABCD-local";
char specifications[] = "5V";

void on_mas_topic(
        uxrSession* session,
        uxrObjectId object_id,
        uint16_t request_id,
        uxrStreamId stream_id,
        struct ucdrBuffer* ub,
        uint16_t length,
        void* args)
{
    (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) length;

    msbot_master topic;
    msbot_master_deserialize_topic(ub, &topic);

    printf("Received master topic: %s, id: %i\n", topic.message, topic.index);

    uint32_t* count_ptr = (uint32_t*) args;
    (*count_ptr)++;
}

void on_topic(
        uxrSession* session,
        uxrObjectId object_id,
        uint16_t request_id,
        uxrStreamId stream_id,
        struct ucdrBuffer* ub,
        uint16_t length,
        void* args)
{
    (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) length;

    HelloWorld topic;
    HelloWorld_deserialize_topic(ub, &topic);

    char key[20];
    snprintf(key, 20, "0x%X%X%X%X", session->info.key[0], session->info.key[1], session->info.key[2],
            session->info.key[3]);
    printf("Session %s: %s (%i)\n", key, topic.message, topic.index);
}

void on_reply(
        uxrSession* session,
        uxrObjectId object_id,
        uint16_t request_id,
        uint16_t reply_id,
        ucdrBuffer* ub,
        uint16_t length,
        void* args)
{
    (void) object_id;
    (void) request_id;
    (void) length;

    //uint64_t result;
    char result[3*32];
    ucdr_deserialize_string(ub, result, sizeof(result));

#ifdef WIN32
    printf("Reply received: %I64u [id: %d]\n", result, reply_id);
#else
    //printf("Reply received: %" PRIu64 " [id: %d]\n", result, reply_id);
    printf("Reply received: %s [id: %d]\n", result, reply_id);
#endif /* ifdef WIN32 */
}

int main(
        int args,
        char** argv)
{
    if (3 > args || 0 == atoi(argv[2]))
    {
        printf("usage: program [-h | --help] | ip port [key]\n");
        return 0;
    }

    char* ip = argv[1];
    char* port = argv[2];
    uint32_t key = (args == 4) ? (uint32_t)atoi(argv[3]) : 0xAAAABBBB;

    // State -- master topic
    uint32_t count = 0;

    // Transport
    uxrUDPTransport transport;
    if (!uxr_init_udp_transport(&transport, UXR_IPv4, ip, port))
    {
        printf("Error at init transport.\n");
        return 1;
    }

    // Session
    uxrSession session;
    uxr_init_session(&session, &transport.comm, key);
    uxr_set_reply_callback(&session, on_reply, false);
    uxr_set_topic_callback(&session, on_topic, NULL);
    uxr_set_topic_callback(&session, on_mas_topic, &count);
    if (!uxr_create_session(&session))
    {
        printf("Error at init session.\n");
        return 1;
    }

    // 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);

    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);

    // Create entities
    uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID);
    const char* participant_xml = "<dds>"
            "<participant>"
            "<rtps>"
            "<name>default_xrce_participant</name>"
            "</rtps>"
            "</participant>"
            "</dds>";
    uint16_t participant_req = uxr_buffer_create_participant_xml(&session, reliable_out, participant_id, 0,
                    participant_xml, UXR_REPLACE);

    uxrObjectId requester_id = uxr_object_id(0x01, UXR_REQUESTER_ID);
    const char* requester_xml = "<dds>"
            "<requester profile_name=\"my_requester\""
            "service_name=\"service_name\""
            "request_type=\"request_type\""
            "reply_type=\"reply_type\">"
            "</requester>"
            "</dds>";
    uint16_t requester_req = uxr_buffer_create_requester_xml(&session, reliable_out, requester_id, participant_id,
                    requester_xml, UXR_REPLACE);

    //-------- publisher and subscriber --------

    //---master topic---
    uxrObjectId mas_topic_id = uxr_object_id(0x01, UXR_TOPIC_ID);     //master topic
    const char* mas_topic_xml = "<dds>"
            "<topic>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</dds>";

   uint16_t mas_topic_req = uxr_buffer_create_topic_xml(&session, reliable_out, mas_topic_id, participant_id, mas_topic_xml,
                    UXR_REPLACE);

    uxrObjectId mas_subscriber_id = uxr_object_id(0x01, UXR_SUBSCRIBER_ID);
    const char* mas_subscriber_xml = "";
    uint16_t mas_subscriber_req = uxr_buffer_create_subscriber_xml(&session, reliable_out, mas_subscriber_id, participant_id,
                    mas_topic_xml, UXR_REPLACE);

    uxrObjectId mas_datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID);
    const char* mas_datareader_xml = "<dds>"
            "<data_reader>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</data_reader>"
            "</dds>";

    uint16_t mas_datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, mas_datareader_id, mas_subscriber_id,
                    mas_datareader_xml, UXR_REPLACE);

    //---master-topic ---

    uxrObjectId topic_id_1_1 = uxr_object_id(0x01, UXR_TOPIC_ID);
    const char* topic_xml_1_1 = "<dds>"
            "<topic>"
            "<name>HelloWorldTopic_1_to_2</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</dds>";
    uint16_t topic_req_1_1 = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id_1_1, participant_id,
                    topic_xml_1_1, UXR_REPLACE);

    uxrObjectId topic_id_1_2 = uxr_object_id(0x02, UXR_TOPIC_ID);
    const char* topic_xml_1_2 = "<dds>"
            "<topic>"
            "<name>HelloWorldTopic_3_to_1</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</dds>";
    uint16_t topic_req_1_2 = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id_1_2, participant_id,
                    topic_xml_1_2, UXR_REPLACE);

    uxrObjectId publisher_id = uxr_object_id(0x01, UXR_PUBLISHER_ID);
    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 = "<dds>"
            "<data_writer>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>HelloWorldTopic_1_to_2</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</data_writer>"
            "</dds>";
    uint16_t datawriter_req = uxr_buffer_create_datawriter_xml(&session, reliable_out, datawriter_id,
                    publisher_id, datawriter_xml, UXR_REPLACE);

    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 = "<dds>"
            "<data_reader>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>HelloWorldTopic_3_to_1</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</data_reader>"
            "</dds>";
    uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id,
                    subscriber_id, datareader_xml, UXR_REPLACE);

    //---------- end PnS -------------------

    // Send create entities message and wait its status

    uint16_t requests[] = {
        participant_req, mas_topic_req, mas_subscriber_req, mas_datareader_req, requester_req, topic_req_1_1, topic_req_1_2, publisher_req, datawriter_req, subscriber_req,
        datareader_req
    };
    uint8_t req_status[sizeof(requests) / 2];

    if (!uxr_run_session_until_all_status(&session, 1000, requests, req_status, 2))
    {
        printf("Error at create entities: participant: %i requester: %i\n", req_status[0], req_status[1]);
        return 1;
    }

    // Request replies
    uxrDeliveryControl delivery_control = {
        0
    };
    delivery_control.max_samples = UXR_MAX_SAMPLES_UNLIMITED;
    uint16_t read_data_req = uxr_buffer_request_data(&session, reliable_out, requester_id, reliable_in,
                    &delivery_control);

    uint16_t read_data_req_topic = uxr_buffer_request_data(&session, reliable_out, datareader_id, reliable_in,
                    &delivery_control);

    uint16_t read_data_req_mas_topic_ = uxr_buffer_request_data(&session, reliable_out, mas_datareader_id, reliable_in,
                    &delivery_control);

   time_t t;

   /* Intializes random number generator */
   srand((unsigned) time(&t));

    // Write requests
    bool connected = true;
    uint32_t requester_count = 0;

    HelloWorld topic;

    while (connected)
    {

       //Update publishing message
       sprintf(topic.message, "Publisher A(1) turn-on %d", rand() % 8);
       printf("Updated messsage is \"%s\"\n", topic.message);

       topic.index = requester_count;

      //uint8_t request[32 * 3] = {
        char request[32 * 3] = {  /* 3 strings  of 32 chars long */
             0
        };

        ucdrBuffer ub;

  //       ucdrBuffer ub_1;
        uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0);
        uxr_prepare_output_stream(&session, reliable_out, datawriter_id, &ub, topic_size);
        HelloWorld_serialize_topic(&ub, &topic);

        ucdr_init_buffer(&ub, request, sizeof(request));
    //    ucdr_serialize_uint32_t(&ub, count);
    //    ucdr_serialize_uint32_t(&ub, count);

    //    ucdr_serialize_uint32_t(&ub, &partname);
    //    ucdr_serialize_uint32_t(&ub, &localpartname);

        ucdr_serialize_string(&ub, partname);
        ucdr_serialize_string(&ub, localpartname);

        uint16_t request_id = uxr_buffer_request(&session, reliable_out, requester_id, request, sizeof(request));
        //printf("Request sent: (%d + %d) [id: %d]\n", count, count, request_id);
        printf("Request sent: (%s + %s) [id: %d]\n", partname, localpartname, request_id);

        connected = uxr_run_session_time(&session, 1000);

        ++requester_count;
    }

    return 0;
}
vibnwis commented 3 years ago

I re-code combining the sample HelloWorld_ and my edited msbotmaster_main.c. The result is somewhat similar, the first code, at higher line works. But as soon as the second publisher begins, the first publisher stops running. Restart the first publisher stops the second publisher. It only allows one publisher at a timer. Please comment. Here is the code.

// 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 "msbot_master.h"
#include "HelloWorld.h"

#include <uxr/client/client.h>

#include <stdio.h> //printf
#include <string.h> //strcmp
#include <stdlib.h> //atoi

#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* ub,
        uint16_t length,
        void* args)
{
    (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) length;

    msbot_master topic;
    msbot_master_deserialize_topic(ub, &topic);

    printf("Received topic: %s, %s, %s, %s, %s, id: %i\n", topic.message, topic.name, topic.id, topic.dof, topic.make, topic.index);

    uint32_t* count_ptr = (uint32_t*) args;
    (*count_ptr)++;
}

void on_topic_1(
        uxrSession* session,
        uxrObjectId object_id,
        uint16_t request_id,
        uxrStreamId stream_id,
        struct ucdrBuffer* ub,
        uint16_t length,
        void* args)
{
    (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) length;

    HelloWorld topic;
    HelloWorld_deserialize_topic(ub, &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)
{
    // CLI
    if (3 > args || 0 == atoi(argv[2]))
    {
        printf("usage: program [-h | --help] | ip port [<max_topics>]\n");
        return 0;
    }

    char* ip = argv[1];
    char* port =  argv[2];
    uint32_t max_topics = (args == 4) ? (uint32_t)atoi(argv[3]) : UINT32_MAX;

    // State
    uint32_t count = 0;

    // Transport
    uxrUDPTransport transport;
    if (!uxr_init_udp_transport(&transport, UXR_IPv4, ip, port))
    {
        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);
    uxr_set_topic_callback(&session, on_topic_1, &count);
    if (!uxr_create_session(&session))
    {
        printf("Error at create session.\n");
        return 1;
    }

    // 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);

    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);

    // Create entities
    uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID);
    const char* participant_xml = "<dds>"
            "<participant>"
            "<rtps>"
            "<name>default_xrce_participant</name>"
            "</rtps>"
            "</participant>"
            "</dds>";
    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 = "<dds>"
            "<topic>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</dds>";
    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_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 = "<dds>"
            "<data_reader>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</data_reader>"
            "</dds>";
    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

    uxrObjectId topic_id_1 = uxr_object_id(0x01, UXR_TOPIC_ID);
    const char* topic_xml_1 = "<dds>"
            "<topic>"
            "<name>HelloWorldTopic</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</dds>";
    uint16_t topic_req_1 = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id_1, participant_id, topic_xml_1,
                    UXR_REPLACE);

    uxrObjectId subscriber_id_1 = uxr_object_id(0x01, UXR_SUBSCRIBER_ID);
    const char* subscriber_xml_1 = "";
    uint16_t subscriber_req_1 = uxr_buffer_create_subscriber_xml(&session, reliable_out, subscriber_id_1, participant_id,
                    subscriber_xml_1, UXR_REPLACE);

    uxrObjectId datareader_id_1 = uxr_object_id(0x01, UXR_DATAREADER_ID);
    const char* datareader_xml_1 = "<dds>"
            "<data_reader>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>HelloWorldTopic</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</data_reader>"
            "</dds>";
    uint16_t datareader_req_1 = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id_1, subscriber_id_1,
                    datareader_xml_1, UXR_REPLACE);

      // Send create entities message and wait its status
    uint8_t status[7];
    uint16_t requests[7] = {
        participant_req, topic_req, subscriber_req, datareader_req,topic_req_1, subscriber_req_1, datareader_req_1
    };
    if (!uxr_run_session_until_all_status(&session, 1000, requests, status, 7))
    {
        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
    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);

     uint16_t read_data_req_1 = uxr_buffer_request_data(&session, reliable_out, datareader_id_1, reliable_in,
                    &delivery_control);

    // 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);
        connected &= uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req_1, &read_data_status, 1);
    }

    // Delete resources
    uxr_delete_session(&session);
    uxr_close_udp_transport(&transport);

    return 0;
}
pablogs9 commented 3 years ago

To subscribe to two publishers, does it need to have two callbacks? one for each publisher. See the code below, I have on_mas_topic() and on_topic().

No, in the XRCE Client all the subscriptions use the same callback, you can determine to what subscription are they related by using the object_id argument.

    uxr_set_topic_callback(&session, on_topic, &count);
    uxr_set_topic_callback(&session, on_topic_1, &count);

The former code is overwriting the callback and you only use on_topic_1

How does the code look like, for uxr_buffer_request_data for subscribing to two topics? see the code below. I have two uxr_buffer_request_data().

It is correct to have a uxr_buffer_request_data for every subscriber because you are asking the agent to provide data for each one in every independent call to the data request function.


In you main loop:

    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);
        connected &= uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req_1, &read_data_status, 1);
    }

You are running the session until the data request message has been acknowledged, but I guess that is better to use uxr_run_session_time or uxr_run_session_timeout (check here)

vibnwis commented 3 years ago

Many thanks. That was very useful information. I have read about using object_id to determine the subscription of interest. However, I could not find any examples relating to that. my doubts on the use of object_id, I have no clues of what object_id values of each subscription. Do you any sample code?

pablogs9 commented 3 years ago

the same object id that you create for example here:

    uxrObjectId datareader_id_1 = uxr_object_id(0x01, UXR_DATAREADER_ID);

will be passed to the callback when this DataReader receives a topic.

vibnwis commented 3 years ago

Many thanks. It progresses a bit, but not entirely. Here are the issues.

  1. MsBOT-Master publisher ran but quit immediately after HelloWorld publisher began or HelloWorld publisher ran but quit immediately after MsBOT-Master publisher began. In other words, only one publisher able to run at a time.
  2. From the screenshot, you can see that the object_id.id is always = 0x01 for both HelloWorld and MsBOT-Master publisher. I have tried to change the value 0x2, see below. However, in on_topic, it appears as 0x1.

Very appreciate your comments, please.

Screenshot from 2021-04-19 21-22-30

uxrObjectId topic_id_1 = uxr_object_id(0x02, UXR_TOPIC_ID); const char* topic_xml_1 = "" "" "HelloWorldTopic" "HelloWorld" "" ""; uint16_t topic_req_1 = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id_1, participant_id, topic_xml_1, UXR_REPLACE);

uxrObjectId subscriber_id_1 = uxr_object_id(0x02, UXR_SUBSCRIBER_ID);
const char* subscriber_xml_1 = "";
uint16_t subscriber_req_1 = uxr_buffer_create_subscriber_xml(&session, reliable_out, subscriber_id_1, participant_id,
                subscriber_xml_1, UXR_REPLACE);

datareader_id_1 = uxr_object_id(0x02, UXR_DATAREADER_ID);
const char* datareader_xml_1 = "<dds>"
        "<data_reader>"
        "<topic>"
        "<kind>NO_KEY</kind>"
        "<name>HelloWorldTopic</name>"
        "<dataType>HelloWorld</dataType>"
        "</topic>"
        "</data_reader>"
        "</dds>";
uint16_t datareader_req_1 = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id_1, subscriber_id_1,
                datareader_xml_1, UXR_REPLACE);
vibnwis commented 3 years ago

Sorry, I was wrong about issue #2 -- Copy and Paste mistake.

vibnwis commented 3 years ago

"/* To know which kind of Topic has been received, we can use the object_id parameter or the request_id. The id of the object_id corresponds to the DataReader that has read the Topic, so it can be useful to discretize among different topics."

Out of curiosity, based on the statement above I wonder how request_id is being generated? as a subscriber, how would I know the values for checking them?

About the quitting issue of one publisher when the other publisher is being executed, I wonder what causes it?

pablogs9 commented 3 years ago

Could you share your code? It's a bit difficult to understand your setup...

vibnwis commented 3 years ago
// 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 "msbot_master.h"
#include "HelloWorld.h"

#include <uxr/client/client.h>

#include <stdio.h> //printf
#include <string.h> //strcmp
#include <stdlib.h> //atoi

#define STREAM_HISTORY  8
#define BUFFER_SIZE     UXR_CONFIG_UDP_TRANSPORT_MTU* STREAM_HISTORY

uxrObjectId datareader_id;
uxrObjectId datareader_id_1;

void on_topic(
        uxrSession* session,
        uxrObjectId object_id,
        uint16_t request_id,
        uxrStreamId stream_id,
        struct ucdrBuffer* ub,
        uint16_t length,
        void* args)
{
    (void) session; (void) object_id; (void) request_id; (void) stream_id; (void) length;

    msbot_master topic;
    msbot_master_deserialize_topic(ub, &topic);

    if (object_id.id == datareader_id.id) {
      printf(" Received MsBOT object_id.id = %d request_id = %d\n", datareader_id.id, request_id);
    }
    else {
      printf(" Received HelloWorld object_id.id = %d request_id = %d\n", datareader_id_1.id, request_id);
    }

    printf("Received topic: %s, %s, %s, %s, %s, id: %i\n", topic.message, topic.name, topic.id, topic.dof, topic.make, topic.index);

    uint32_t* count_ptr = (uint32_t*) args;
    (*count_ptr)++;
}

int main(
        int args,
        char** argv)
{
    // CLI
    if (3 > args || 0 == atoi(argv[2]))
    {
        printf("usage: program [-h | --help] | ip port [<max_topics>]\n");
        return 0;
    }

    char* ip = argv[1];
    char* port =  argv[2];
    uint32_t max_topics = (args == 4) ? (uint32_t)atoi(argv[3]) : UINT32_MAX;

    // State
    uint32_t count = 0;

    // Transport
    uxrUDPTransport transport;
    if (!uxr_init_udp_transport(&transport, UXR_IPv4, ip, port))
    {
        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;
    }

    // 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);

    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);

    // Create entities
    uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID);
    const char* participant_xml = "<dds>"
            "<participant>"
            "<rtps>"
            "<name>default_xrce_participant</name>"
            "</rtps>"
            "</participant>"
            "</dds>";
    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 = "<dds>"
            "<topic>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</dds>";
    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_create_subscriber_xml(&session, reliable_out, subscriber_id, participant_id,
                    subscriber_xml, UXR_REPLACE);

    datareader_id = uxr_object_id(0x01, UXR_DATAREADER_ID);
    const char* datareader_xml = "<dds>"
            "<data_reader>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</data_reader>"
            "</dds>";
    uint16_t datareader_req = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id, subscriber_id,
                    datareader_xml, UXR_REPLACE);

    // second subscriber

    uxrObjectId topic_id_1 = uxr_object_id(0x02, UXR_TOPIC_ID);
    const char* topic_xml_1 = "<dds>"
            "<topic>"
            "<name>HelloWorldTopic</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</dds>";
    uint16_t topic_req_1 = uxr_buffer_create_topic_xml(&session, reliable_out, topic_id_1, participant_id, topic_xml_1,
                    UXR_REPLACE);

    uxrObjectId subscriber_id_1 = uxr_object_id(0x02, UXR_SUBSCRIBER_ID);
    const char* subscriber_xml_1 = "";
    uint16_t subscriber_req_1 = uxr_buffer_create_subscriber_xml(&session, reliable_out, subscriber_id_1, participant_id,
                    subscriber_xml_1, UXR_REPLACE);

    datareader_id_1 = uxr_object_id(0x02, UXR_DATAREADER_ID);
    const char* datareader_xml_1 = "<dds>"
            "<data_reader>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>HelloWorldTopic</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</data_reader>"
            "</dds>";
    uint16_t datareader_req_1 = uxr_buffer_create_datareader_xml(&session, reliable_out, datareader_id_1, subscriber_id_1,
                    datareader_xml_1, UXR_REPLACE);

    // end of second subsriber

    // Send create entities message and wait its status
    uint8_t status[7];
    uint16_t requests[7] = {
        participant_req, topic_req, subscriber_req, datareader_req, topic_req_1, subscriber_req_1, datareader_req_1
    };
    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
    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);

    uint16_t read_data_req_1 = uxr_buffer_request_data(&session, reliable_out, datareader_id_1, reliable_in,
                    &delivery_control);

    uint8_t read_data_status;

    // Read topics

    if (!uxr_run_session_until_all_status(&session, UXR_TIMEOUT_INF, &read_data_req, &read_data_status, 1))
    {
        printf("Error at create entities: participant: %i topic: %i subscriber: %i datareader: %i\n", status[0],
                status[1], status[2], status[3]);
        return 1;
    }

    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);
        connected = uxr_run_session_time(&session, 1000);
    }

    // Delete resources
    uxr_delete_session(&session);
    uxr_close_udp_transport(&transport);

    return 0;
}
vibnwis commented 3 years ago

HelloWorld_main.c <-- Publisher #1

// 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 <uxr/client/client.h>
#include <ucdr/microcdr.h>

#include <stdio.h> //printf
#include <string.h> //strcmp
#include <stdlib.h> //atoi

#define STREAM_HISTORY  8
#define BUFFER_SIZE     UXR_CONFIG_UDP_TRANSPORT_MTU* STREAM_HISTORY

int main(
        int args,
        char** argv)
{
    // CLI
    if (3 > args || 0 == atoi(argv[2]))
    {
        printf("usage: program [-h | --help] | ip port [<max_topics>]\n");
        return 0;
    }

    char* ip = argv[1];
    char* port = argv[2];
    uint32_t max_topics = (args == 4) ? (uint32_t)atoi(argv[3]) : UINT32_MAX;

    // Transport
    uxrUDPTransport transport;
    if (!uxr_init_udp_transport(&transport, UXR_IPv4, ip, port))
    {
        printf("Error at create transport.\n");
        return 1;
    }

    // Session
    uxrSession session;
    uxr_init_session(&session, &transport.comm, 0xAAAABBBB);
    if (!uxr_create_session(&session))
    {
        printf("Error at create session.\n");
        return 1;
    }

    // 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);

    uint8_t input_reliable_stream_buffer[BUFFER_SIZE];
    uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY);

    // Create entities
    uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID);
    const char* participant_xml = "<dds>"
            "<participant>"
            "<rtps>"
            "<name>default_xrce_participant</name>"
            "</rtps>"
            "</participant>"
            "</dds>";
    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 = "<dds>"
            "<topic>"
            "<name>HelloWorldTopic</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</dds>";
    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_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 = "<dds>"
            "<data_writer>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>HelloWorldTopic</name>"
            "<dataType>HelloWorld</dataType>"
            "</topic>"
            "</data_writer>"
            "</dds>";
    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];
    uint16_t requests[4] = {
        participant_req, topic_req, publisher_req, datawriter_req
    };
    if (!uxr_run_session_until_all_status(&session, 1000, requests, status, 4))
    {
        printf("Error at create entities: participant: %i topic: %i publisher: %i datawriter: %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!"
        };

        ucdrBuffer ub;
        uint32_t topic_size = HelloWorld_size_of_topic(&topic, 0);
        uxr_prepare_output_stream(&session, reliable_out, datawriter_id, &ub, topic_size);
        HelloWorld_serialize_topic(&ub, &topic);

        printf("Send topic: %s, id: %i\n", topic.message, topic.index);
        connected = uxr_run_session_time(&session, 1000);
    }

    // Delete resources
    uxr_delete_session(&session);
    uxr_close_udp_transport(&transport);

    return 0;
}
vibnwis commented 3 years ago

MsBOT-Master -- Publisher #2

// 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 "msbot_master.h"

#include <uxr/client/client.h>
#include <ucdr/microcdr.h>

#include <stdio.h> //printf
#include <string.h> //strcmp
#include <stdlib.h> //atoi

#define STREAM_HISTORY  8
#define BUFFER_SIZE     UXR_CONFIG_UDP_TRANSPORT_MTU* STREAM_HISTORY

int main(
        int args,
        char** argv)
{
    // CLI
    if (3 > args || 0 == atoi(argv[2]))
    {
        printf("usage: program [-h | --help] | ip port [<max_topics>]\n");
        return 0;
    }

    char* ip = argv[1];
    char* port = argv[2];
    uint32_t max_topics = (args == 4) ? (uint32_t)atoi(argv[3]) : UINT32_MAX;

    // Transport
    uxrUDPTransport transport;
    if (!uxr_init_udp_transport(&transport, UXR_IPv4, ip, port))
    {
        printf("Error at create transport.\n");
        return 1;
    }

    // Session
    uxrSession session;
    uxr_init_session(&session, &transport.comm, 0xAAAABBBB);
    if (!uxr_create_session(&session))
    {
        printf("Error at create session.\n");
        return 1;
    }

    // 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);

    uint8_t input_reliable_stream_buffer[BUFFER_SIZE];
    uxr_create_input_reliable_stream(&session, input_reliable_stream_buffer, BUFFER_SIZE, STREAM_HISTORY);

    // Create entities
    uxrObjectId participant_id = uxr_object_id(0x01, UXR_PARTICIPANT_ID);
    const char* participant_xml = "<dds>"
            "<participant>"
            "<rtps>"
            "<name>default_xrce_participant</name>"
            "</rtps>"
            "</participant>"
            "</dds>";
    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 = "<dds>"
            "<topic>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</dds>";
    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_create_publisher_xml(&session, reliable_out, publisher_id, participant_id,
                    publisher_xml, UXR_REPLACE);

    uxrObjectId datawriter_id = uxr_object_id(0x02, UXR_DATAWRITER_ID);
    const char* datawriter_xml = "<dds>"
            "<data_writer>"
            "<topic>"
            "<kind>NO_KEY</kind>"
            "<name>msbot_masterTopic</name>"
            "<dataType>msbot_master</dataType>"
            "</topic>"
            "</data_writer>"
            "</dds>";
    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];
    uint16_t requests[4] = {
        participant_req, topic_req, publisher_req, datawriter_req
    };
    if (!uxr_run_session_until_all_status(&session, 1000, requests, status, 4))
    {
        printf("Error at create entities: participant: %i topic: %i publisher: %i datawriter: %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)
    {
        msbot_master topic = {
            ++count, "MSBOT_MASTER", "MSBOT_V1","X100Y100Z100", "8-4-2021","MASSEY_ENGINEERING_DEP"
        };
        ucdrBuffer ub;
        uint32_t topic_size = msbot_master_size_of_topic(&topic, 0);
        uxr_prepare_output_stream(&session, reliable_out, datawriter_id, &ub, topic_size);
        msbot_master_serialize_topic(&ub, &topic);

        printf("Send topic: %s, %s, %s, %s, %s, id: %i\n", topic.message, topic.name, topic.id, topic.dof, topic.make, topic.index);
        connected = uxr_run_session_time(&session, 5000);
    }

    // Delete resources
    uxr_delete_session(&session);
    uxr_close_udp_transport(&transport);

    return 0;
}
pablogs9 commented 3 years ago

For next times, you can upload files to Github comments, and also you can format your code

pablogs9 commented 3 years ago

Share also msbot_master.h and msbot_master.c please

vibnwis commented 3 years ago

Apologies, still reading the "format your code". Not fully understand that for now. Hence, still uploading them through comment space.

//msbot_master.h
// Copyright 2016 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.

/*! 
 * @file msbot_master.h
 * This header file contains the declaration of the described types in the IDL file.
 *
 * This file was generated by the tool gen.
 */

#ifndef _msbot_master_H_
#define _msbot_master_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdint.h>
#include <stdbool.h>

/*!
 * @brief This struct represents the structure msbot_master defined by the user in the IDL file.
 * @ingroup MSBOT_MASTER
 */
typedef struct msbot_master
{
    uint32_t index;
    char message[255];

    char name[255];

    char id[255];

    char dof[255];

    char make[255];

} msbot_master;

struct ucdrBuffer;

bool msbot_master_serialize_topic(struct ucdrBuffer* writer, const msbot_master* topic);
bool msbot_master_deserialize_topic(struct ucdrBuffer* reader, msbot_master* topic);
uint32_t msbot_master_size_of_topic(const msbot_master* topic, uint32_t size);

#ifdef __cplusplus
}
#endif

#endif // _msbot_master_H_

-----------------------------------------------------------------------------------
// Copyright 2016 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.

/*! 
 * @file msbot_master.c
 * This source file contains the definition of the described types in the IDL file.
 *
 * This file was generated by the tool gen.
 */

#include "msbot_master.h"

#include <ucdr/microcdr.h>
#include <string.h>

bool msbot_master_serialize_topic(ucdrBuffer* writer, const msbot_master* topic)
{
    (void) ucdr_serialize_uint32_t(writer, topic->index);

    (void) ucdr_serialize_string(writer, topic->message);

    (void) ucdr_serialize_string(writer, topic->name);

    (void) ucdr_serialize_string(writer, topic->id);

    (void) ucdr_serialize_string(writer, topic->dof);

    (void) ucdr_serialize_string(writer, topic->make);

    return !writer->error;
}

bool msbot_master_deserialize_topic(ucdrBuffer* reader, msbot_master* topic)
{
    (void) ucdr_deserialize_uint32_t(reader, &topic->index);

    (void) ucdr_deserialize_string(reader, topic->message, 255);

    (void) ucdr_deserialize_string(reader, topic->name, 255);

    (void) ucdr_deserialize_string(reader, topic->id, 255);

    (void) ucdr_deserialize_string(reader, topic->dof, 255);

    (void) ucdr_deserialize_string(reader, topic->make, 255);

    return !reader->error;
}

uint32_t msbot_master_size_of_topic(const msbot_master* topic, uint32_t size)
{
    uint32_t previousSize = size;
    size += ucdr_alignment(size, 4) + 4;

    size += ucdr_alignment(size, 4) + 4 + (uint32_t)strlen(topic->message) + 1;

    size += ucdr_alignment(size, 4) + 4 + (uint32_t)strlen(topic->name) + 1;

    size += ucdr_alignment(size, 4) + 4 + (uint32_t)strlen(topic->id) + 1;

    size += ucdr_alignment(size, 4) + 4 + (uint32_t)strlen(topic->dof) + 1;

    size += ucdr_alignment(size, 4) + 4 + (uint32_t)strlen(topic->make) + 1;

    return size - previousSize;
}
pablogs9 commented 3 years ago

Ok, I have done some minor changes but the main point of your app is that you are using the same client key for both publishers.

Check the uxr_init_session(&session, &transport.comm, 0xAAAABBBB);. Every session must have a different key.

Find attached my example: test.zip

vibnwis commented 3 years ago

Very appreciate that. I tested it as well. They work.

I was wondering if you know how to get the values of request_id? where it can you use with object_id for checking the topic of interest

pablogs9 commented 3 years ago

I don't know if I understand the question...

In the topic callback, the parameter request_id will be related to the XRCE request that asked for that data in this case it should be one of these two:

uint16_t read_data_req = uxr_buffer_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control);
uint16_t read_data_req_1 = uxr_buffer_request_data(&session, reliable_out, datareader_id_1, reliable_in, &delivery_control);
vibnwis commented 3 years ago

Yes, that is exactly what I question is. Thank you.

On Mon, 19 Apr 2021 at 23:18, Pablo Garrido @.***> wrote:

I don't know if I understand the question...

In the topic callback, the parameter request_id will be related to the XRCE request that asked for that data in this case it should be one of these two:

uint16_t read_data_req = uxr_buffer_request_data(&session, reliable_out, datareader_id, reliable_in, &delivery_control);uint16_t read_data_req_1 = uxr_buffer_request_data(&session, reliable_out, datareader_id_1, reliable_in, &delivery_control);

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/eProsima/Micro-XRCE-DDS/issues/86#issuecomment-822389724, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADCYQVSOVZEFFDSFK4JQTP3TJQGR5ANCNFSM43EDN2DA .

pablogs9 commented 3 years ago

Ok, closing.