Hi,
Rtiddsspy has the ability to discover topics on the network as well as display the contents of the samples. And not just simple messages (strings, ints) but ones that have hierarchy. I'm interested to know how it does it.
- How does it discover all topics in the current domain? get_discovered_topics()?
- How does it retrieve the structure of a particular topic? get_discovered_topic_data()?
- How should I then subscribe to all the topics?
- How should I then print out the contents of the sample?
I know there are existing tools like rtiddsspy and DDS Wireshark, but they only do a subset of what I'm looking to do.
Many thanks,
Fidel
Hello Fidel,
I will try to answer your questions in order:
1) How does it discover all topics in the current domain? get_discovered_topics()?
To do this you use the so called Discovery Builtin Readers. The basic idea is that DDS propagates discovery data as any other kind of data only that every application automatically publishes and subscribes that data and that the topic names and associated data-types are pre-defined in the system. This is all part of the DDS specification.
You can access the builtin DataReaders and 'listen' and read these DataReaders as any other DataReader. When you read data on this topics you get the information about remote entities that have been discovered (DomainParticipants, DataWriters, DataReaders).
For example the information on a remote DataWriter is conveyed as a sample with type PublicationBuiltinTopicData
There you can see members for the name of the Topic, the name of the Type, the different QoS Policies, and even a description of the type itself. I will elaborate on this further on the answer to your second question below.
There is a HOWTO titled Detect the presence of DomainParticipants, DataWriters and DataReaders in the DDS Domain that describes everything in detail and has some working sample code as well. Here is a Java example that shows how to monitor the discovery data. It is in the file MonitorDiscoveryInformation.java
2) How does it retrieve the structure of a particular topic? get_discovered_topic_data()?
The description of the data-type associated with a DataWriter (or a DataReader) is also propagated via Discovery, it is one of the attributes in the data that you read using the builtin DataReaders mentioned in (1) above.
Note that these API's will change a little bit in future versions because we are rolling out support for the DDS Extensible Types specification which defines slightly different ways to do this. But the ideas and approach are very similar.
The type information is carried in the field called type_code which appears both in the PublicationBuiltinTopicData (referring to a discovered remote DataWriter) and in the SubscriptionBuiltinTopicData (referring to a discovered remote DataReader). These fields are of type TypeCode Using the operations supported by the TypeCode you can extract all the information about the data-type.For example, if it was a structure you can get its name, the number of members, name of each member, TypeCode of each member, etc. So you can recursively navigate the whole type. There is even an operation on the TypeCode called printIDL which will print the IDL representation of that data-type.
In the File Exchange there is a Java example that shows how to monitor the discovery data. It is in the file MonitorDiscoveryTypes.java
3) How should I then subscribe to all the topics?
Once you have discovered a DataWriter you have the name of the Topic and the Associated data-type. At this point what you need to do is to
The easiest way to do this is with an example. I will post one when get a chance. But in the meantime I will give you some pointers to the steps and API calls you need to use.
a) Register the data-type into your DomainParticipant, if this is the first time you see that data-type name
This is done using the DynamicDataTypeSupport Once you discover the TypeCode that describes a new data-type you have discovered you can construct a new DynamicDataTypeSupport using its constructor which takes the TypeCode as a parameter.
Once you have a DynamicDataTypeSupport. You call its register_type operation to register that data-type in the DomainParticipant with a type-name that matches the one in the DataWriter you discovered.
b) Create a Topic with that associated data-type, if this is the first time you see that Topic name.
After (a) the DomainParticipant knows about the data-type so create the Topic using the regular create_topic operation on the DomainParticipant
c) Create a DataReader for that Topic, again if this is the first time you see that Topic name.
After (b) you have a Topic so you create a DataReader using the regular create_datareader() operation on a Subscriber.
The DataReader you will get is of type DynamicDataReader Which means that when you read from it you will get samples with the type DynamicData
In the File Exchange there is a Java example that shows how to perform the above steps to dynamically register a type that matches whet was discovered, create a Topic, a DynamicDataReader and read the data. It is in MonitorData.java
4) How should I then print out the contents of the sample?
The DynamicData object provides methods to access the members, iterate over them, etc. One convenient method is print which will prints the contents of the sample to a file or console. This is what is used in the It is in MonitorData.java example.
Regards,
Gerardo
Gerardo - wow! That is one fantastic response. It's got the perfect level of detail. Thank you very much for taking the time to respond, I am extremely grateful.
Kind regards,
Fidel
Hi,
Glad the answer helps! I updated my original answer to point to an example I created that monitors the data values.
Gerardo
Hi Gerardo,
Prior to your step by step descriptions above, I got a question. I only need to create 1 participant to subscribe to many topics of different typecodes right?
Jeslene
Hi Jeslene,
Yes this is right a single DomainParticipant is all you should need. You only need to create mutiple DomainParticipant entities in a single process/application if you want to join different domain IDs which represent separate isolated data-spaces. This does not sound like it would be your use-case... so a single DomainParticipant is enough.
Gerardo
Hi Gerardo,
The monitorData.java example is great.
My question is about properly stoping the wait set.
How can we properly stop the wait set at the end of the application ?
I didn't find any stop or interupt method.
Thanks
You can use what amounts to a software signal to trigger the WaitSet, and then treat the signal as a "we're done" in the condition handling.
See the documentation for "GuardCondition".
Thanks rip.
To summuarise, here is the code I use to create the WaitSet:
And here the loop :
Thanks
Hello again,
To complete this example, I try to detect unsubscibed data readers/writters. I use the info.view_state to differenciate new writer from deleted one as descibe in MonotiorData.java. Here is my code sample :
Unfortunatly I've got empty names when unsubscribing. So I don't know who has left :
How can I know the type name, topic name and writer name that has left ?
Thanks
This is covered on other posts on the forum. Here's a place to start: Detecting Leavers
Summary:
Knowing who has left wasn't supported as of 5.1.x. It might have been added for 5.2, however I don't have the release notes in front of me. If not, you have to use a method to track who has joined so that you can match who has left with your cached material. The signal you receive is simply "entity with UUID xyz has left", so you have to track back to what information you collected when the entity joined.
The reasoning is that, because it has left, its information is not relevant going forward. That does make sense as a standard design criteria in a system (it's gone, so why will we (in the future) care?), but there are legitimate cases where it would be interesting to know who left (the Security domain for example...it would certainly be helpful to the application to know that authenticated user Foo has disconnected, so if we get more information from Foo, we need to be really skeptical about its provenance).
hth,
rip
Hi,
Here is how I do to detect leavers :
First you need to suibscribe for all kind of notifications :
Then you can detect if it is a new data or not:
Hi hope that will help people.
Concerning detection of already existing publishers and subscribers I've few difficulties:
If I set domainParticipantQos.entity_factory.autoenable_created_entities = false; and do participant.enable(); then nothing works.
If I also try to enable the buildin subscriber, I get the following error :
How can I be sure to properly enable the participant and it's built in topics ?
Thanks
ps: here is my initialisation code:
Hi there, I'm currently getting the same error as Yoann above. I am trying to enable the builtin subscriber after creating a participant in disabled mode.
This seems to be the approach suggested for detecting existing participants upon creating a participant: https://community.rti.com/forum-topic/discovering-subscription-and-publication-data
Enabling just the participant does nothing, as Yoann mentions above.
Thanks
Hello,
This may help:
https://community.rti.com/examples/builtin-topics
There's code attached and you may use it to set up your solution.
Good luck,
Roy.
Ah thanks Roy!
For anyone here in the future: The key to being able to enable the participant, the builtin subscriber, and any data readers created from it is to use the DomainParticipantFactory.TheParticipantFactory to create your participant, instead of one that you instantiate yourself.