Search code examples
acedata-distribution-servicetao

Receive messages only from a specific DDS topic instance?


I'm using OpenDDS v3.6, and trying to send a message to a specific DDS peer, one of many. In the IDL, the message structure looks like the following:

module Test
{
#pragma DCPS_DATA_TYPE "Test::MyMessage"
#pragma DCPS_DATA_KEY "Test::MyMessage dest_id"
    struct MyMessage {
        short dest_id;
        string txt;
    };
};

My understanding is that because the data key is unique, this is a new instance of the topic being written to, and any further msgs written w/ the same data key send to this specific instance of the topic. My send code is as follows:

DDS::ReturnCode_t ret;
Test::MyMessage msg;

// populate msg
msg.dest_id = n;

DDS::InstanceHandle_t handle;

handle = msg_writer->register_instance(msg);

ret = msg_writer->write(msg, handle);

So now I need to figure out how to get the receiving peer to read only from this topic instance and not receive all the other messages being sent to other peers. I started with the following, but not sure how to properly select a specific topic instance.

DDS::InstanceHandle_t instance;

status = msg_dr->take_next_instance(spec, si, 1, DDS::ANY_SAMPLE_STATE, 
    DDS::ANY_VIEW_STATE, DDS::ANY_INSTANCE_STATE);

Any help much appreciated.


Solution

  • The easiest way to achieve what you are looking for is by using a ContentFilteredTopic. This class is a specialization of the TopicDescription class and allows you to specify an expression (like a SQL WHERE-clause) of the samples that you are interested in.

    Suppose you want your DataReader to only receive samples with dest_id equal to 42, then the corresponding code for creating the ContentFilteredTopic would look something like

    DDS::ContentFilteredTopic_var cft =
                  participant->create_contentfilteredtopic("MyTopic-Filtered",
                                                           topic,
                                                           "dest_id = 42",
                                                           StringSeq());
    

    From there on, you create your DataReader using cft as the parameter for the TopicDescription. The resulting reader will look like a regular DataReader, except that it only receives the desired samples and nothing else. Since the field dest_id happens to be the field that identifies the instance, the end result is that you will only have one instance in your DataReader.

    You can check out the DDS specification (section 7.1.2.3.3) or OpenDDS Developer's Guide (section 5.2) for more details.