6. Tutorials¶
6.1. Hello World Example¶
The purpose of this example is to get you started with Web Integration Service. We will start from an empty configuration, then add applications and entities using Web Integration Service’s REST API.
To run Web Integration Service from your command shell, go to the installation directory and enter:
$NDDSHOME/bin/rtiwebintegrationservice -cfgName default
This will start an instance of Web Integration Service with an empty
configuration. By default, Web Integration Service will listen for
HTTP requests on port 8080. To set a different listening port, use the
-listeningPorts <portsToListen>
argument. For instance:
$NDDSHOME/bin/rtiwebintegrationservice -cfgName default \
-listeningPorts 8081
To enable HTTPS, append an "s"
to the ports specified
with -listeningPorts
. Use -sslCertificate
to specify the path to
the certificate to be used by the web server when using HTTPS. The certificate
file must combine both the certificate and the private key in the same
file. Here is an example:
$NDDHSOME/bin/rtiwebintegrationservice -cfgName default \
-listeningPorts 8081s -sslCertificate ~/.certificates/some_cert.pem
For a complete list of command-line arguments, see
Section 3.3 or run
rtiwebintegrationservice -help
.
Now that we have a Web Integration Service instance running, we are
going to configure a scenario via REST API calls. In particular, we want
to create an application that will include entities to publish and subscribe
to HelloWorldTopic
topics.
6.1.1. Defining Types¶
Before creating any DDS entity, we first need to define the data types our
application will be sending and receiving. The data type associated with
HelloWorldTopic
consists of two strings and a numeric counter:
- The first string contains the name of the message’s sender. This field is a “key” because it indicates the identity of the data object.
- The second string contains the message itself.
- The third field is a simple counter that the application increments with each sent message.
Web Integration Service uses the Dynamic Data API, so the data type must be
defined in the XML configuration for its later dynamic instantiation. This is accomplished by adding the type definition within the <types>
tag:
<types>
<const name="MAX_NAME_LEN" type="long" value="64"/>
<const name="MAX_MSG_LEN" type="long" value="128"/>
<struct name="HelloWorld">
<member name="sender" type="string" key="true" stringMaxLength="MAX_NAME_LEN"/>
<member name="message" type="string" stringMaxLength="MAX_MSG_LEN"/>
<member name="count" type="long"/>
</struct>
</types>
To load the types we have defined, we need to call the POST method
on /types
and pass the XML type representation in the body of the
HTTP request. In this example, as well as in the rest of examples, we
provide both a raw HTTP Request and the curl
command that needs to be
run to execute the request.
POST /dds/rest1/types HTTP/1.1
Host: <host>[:<port>]
Content-Length: 381
Content-Type: application/dds-web+xml
Cache-Control: no-cache
<types>
<const name="MAX_NAME_LEN" type="long" value="64"/>
<const name="MAX_MSG_LEN" type="long" value="128"/>
<struct name="HelloWorld">
<member name="sender" type="string" key="true" stringMaxLength="MAX_NAME_LEN"/>
<member name="message" type="string" stringMaxLength="MAX_MSG_LEN"/>
<member name="count" type="long"/>
</struct>
</types>
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<types>
<const name="MAX_NAME_LEN" type="long" value="64"/>
<const name="MAX_MSG_LEN" type="long" value="128"/>
<struct name="HelloWorld">
<member name="sender" type="string" key="true" stringMaxLength="MAX_NAME_LEN"/>
<member name="message" type="string" stringMaxLength="MAX_MSG_LEN"/>
<member name="count" type="long"/>
</struct>
</types>' http://<host>[:<port>]/dds/rest1/types
6.1.2. Listing Types¶
You can check that the types were loaded correctly by calling GET
on /types
:
GET /dds/rest1/types HTTP/1.1
Host: <host>[:<port>]
Cache-Control: no-cache
curl -X GET -H "Cache-Control:no-cache" http://<host>[:<port>]/dds/rest1/types
6.1.3. Creating Applications¶
In Web Integration Service, applications are aggregations of DomainParticipants with a common goal. DomainParticipants may:
- Register types—the
<register_type>
tag specifies a type definition that will be registered in the DomainParticipant. - Create Topics—the
<topic>
tag specifies a Topic by associating it with a<register_type>
that contains the type information. - Create Publishers—the
<publisher>
tag specifies a publisher that will be registered in the DomainPartipant. Publishers can create DataWriters using the<data_writer>
tag. - Create Subscribers—the
<subscriber>
tag specifies a Subscriber that will be registered in the DomainParticipant. Subscribers can create DataReaders using the<data_reader>
tag.
Our example Application, which we will call ExampleApplication
, defines a
single DomainParticipant named MyParticipant
. This participant operates in
Domain 0 and:
- Registers
HelloWorldType
, which refers to theHelloWorld
type posted before. - Creates
HelloWorldTopic
, which is associated with the registeredHelloWorldType
. - Creates a Publisher called
MyPublisher
, which creates a DataWriter ofHelloWorldTopic
calledHelloWorldWriter
. - Creates a Subscriber called
MySubscriber
, which creates a DataReader ofHelloWorldTopic
calledHelloWorldReader
.
Here is the XML representation of ExampleApplication
:
<application name="ExampleApplication">
<domain_participant name="MyParticipant" domain_id="0">
<register_type name="HelloWorldType" type_ref="HelloWorld"/>
<topic name="HelloWorldTopic" register_type_ref="HelloWorldType"/>
<publisher name="MyPublisher">
<data_writer name="HelloWorldWriter"
topic_ref="HelloWorldTopic"/>
</publisher>
<subscriber name="MySubscriber">
<data_reader name="HelloWorldReader" topic_ref="HelloWorldTopic"/>
</subscriber>
</domain_participant>
</application>
To create ExampleApplication
, along with all its contained entities,
we must call POST
on /applications
and pass in the XML
representation of the application in the body of the HTTP request:
POST /dds/rest1/applications HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 553
Cache-Control: no-cache
<application name="ExampleApplication">
<domain_participant name="MyParticipant" domain_id="0">
<register_type name="HelloWorldType" type_ref="HelloWorld"/>
<topic name="HelloWorldTopic" register_type_ref="HelloWorldType"/>
<publisher name="MyPublisher">
<data_writer name="HelloWorldWriter" topic_ref="HelloWorldTopic"/>
</publisher>
<subscriber name="MySubscriber">
<data_reader name="HelloWorldReader" topic_ref="HelloWorldTopic"/>
</subscriber>
</domain_participant>
</application>
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<application name="ExampleApplication">
<domain_participant name="MyParticipant" domain_id="0">
<register_type name="HelloWorldType" type_ref="HelloWorld"/>
<topic name="HelloWorldTopic" register_type_ref="HelloWorldType"/>
<publisher name="MyPublisher">
<data_writer name="HelloWorldWriter" topic_ref="HelloWorldTopic"/>
</publisher>
<subscriber name="MySubscriber">
<data_reader name="HelloWorldReader" topic_ref="HelloWorldTopic"/>
</subscriber>
</domain_participant>
</application>' http://<host>[:<port>]/dds/rest1/applications
To check that the defined DomainParticipants, Publishers, Subscribers, DataWriters, and DataReaders were successfully created, call GET on:
/applications/ExampleApplication/domain_participants
,/applications/ExampleApplication/domain_participants/MyParticipant/publishers
/applications/ExampleApplication/domain_participants/MyParticipant/subscribers
,/applications/ExampleApplication/domain_participants/MyParticipant/publishers/MyPublisher/data_writers
, or/applications/ExampleApplication/domain_participants/MyParticipant/subscribers/MySubsriber/data_readers
, respectively.
For instance, to list all the DataWriters within MyPublisher
, call:
GET /dds/rest1/applications/ExampleApplication/domain_participants/MyParticipant/publishers/MyPublisher/data_writers HTTP/1.1
Host: <host>[:<port>]
Cache-Control: no-cache
curl -X GET -H "Cache-Control:no-cache" http://<host>[:<port>]/dds/rest1/applications/ExampleApplication/domain_participants/MyParticipant/publishers/MyPublisher/data_writers
6.1.4. Sending and Receiving Samples¶
6.1.4.1. Sending Samples¶
Once the DataWriter is available, you can start writing data samples. The XML
representation of a HelloWorldType
data sample follows this structure:
<data>
<sender>Fernando</sender>
<message>Hello World!</message>
<count>0</count>
</data>
To write a new data sample, call POST
on /applications/ExampleApplication/domain_participants/MyParticipant/publishers/MyPublisher/data_writers/HelloWorldWriter
and pass in the XML representation of the data sample:
POST /dds/rest1/applications/ExampleApplication/domain_participants/MyParticipant/publishers/MyPublisher/data_writers/HelloWorldWriter HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 101
Cache-Control: no-cache
<data>
<sender>Fernando</sender>
<message>Hello World!</message>
<count>0</count>
</data>
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<data>
<sender>Fernando</sender>
<message>Hello World!</message>
<count>0</count>
</data>' http://<host>[:<port>]/dds/rest1/applications/ExampleApplication/domain_participants/MyParticipant/publishers/MyPublisher/data_writers/HelloWorldWriter
6.1.4.2. Receiving Samples¶
To read the samples available on the DataReader’s cache, call GET
on /applications/ExampleApplication/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers
:
GET /dds/rest1/applications/ExampleApplication/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers/HelloWorldReader HTTP/1.1
Host: <host>[:<port>]
Cache-Control: no-cache
curl -X GET -H "Cache-Control:no-cache" http://<host>[:<port>]/dds/rest1/applications/ExampleApplication/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers/HelloWorldReader
Response
The response is a sequence with the samples read, which includes sample information (i.e., information pertaining to the associated Data instance sample) and sample data (i.e., the actual received data):
HTTP/1.1 200 Samples read
Content-Type: application/dds-web+xml
Cache-Control: no-cache
Content-Length: 537
Date: Fri, 04 Mar 2016 18:50:35 GMT
<read_sample_seq>
<sample>
<read_sample_info>
<source_timestamp>
<sec>1457117216</sec>
<nanosec>260702000</nanosec>
</source_timestamp>
<valid_data>true</valid_data>
<instance_handle>
580BA4179B1A6D6B4CD7CE4F54B3B63C
</instance_handle>
<instance_state>ALIVE</instance_state>
<sample_state>NOT_READ</sample_state>
<view_state>NEW</view_state>
</read_sample_info>
<data>
<sender>Fernando</sender>
<message>Hello World!</message>
<count>0</count>
</data>
</sample>
</read_sample_seq>
6.2. Shapes Demo¶
In the previous example, we started off with an embedded empty configuration
to which—using the REST API—we added an application and different DDS entities
to send and receive HelloWorldTopic
data samples. In this example, we
will use another embedded configuration that contains predefined entities
to communicate with RTI Shapes Demo.
The embedded shapesDemoTutorial
configuration can be found in the following
configuration file: $NDDSHOME/resource/xml/RTI_WEB_INTEGRATION_SERVICE.xml
.
Let’s analyze the different components it contains.
6.2.1. Types Definition¶
The first thing you will find in RTI_WEB_INTEGRATION_SERVICE.xml
is the
definition of a data type called ShapeType
. This is the type that all
the topics that RTI Shapes Demo publishes and subscribes to
(i.e., Square
, Triangle
, and Circle
) are associated with. Here
is its XML representation:
<types>
<const name="MAX_COLOR_LEN" type="long" value="128"/>
<struct name="ShapeType">
<member name="color" type="string" stringMaxLength="128" key="true"/>
<member name="x" type="long"/>
<member name="y" type="long"/>
<member name="shapesize" type="long"/>
</struct>
</types>
6.2.2. Domain Library¶
In RTI_WEB_INTEGRATION_SERVICE.xml
you will also find a domain library
and a domain. Domain libraries provide a way to organize different template
domains that can be used in the definition of DomainParticipants. Domains
represent data spaces where information can be shared by means of reading and
writing the same Topics (which need to be associated with a registered
data type). Therefore, in a <domain>
tag you can specify Topics and
their data types.
Our domain library contains a ShapesDomain
that pre-registers
ShapeType
and creates a Square
topic associated with it.
DomainParticipants referring to the ShapesDomainLibrary::ShapeDomain
domain will automatically instantiate these entities upon creation.
Here is the XML representation of ShapesDomainLibrary
, as defined in RTI_WEB_INTEGRATION_SERVICE.xml
:
<domain_library name="ShapesDomainLibrary">
<domain name="ShapesDomain" domain_id="0">
<register_type name="ShapeType" type_ref="ShapeType" />
<topic name="Square" register_type_ref="ShapeType" />
</domain>
</domain_library>
6.2.3. Shapes Demo Configuration¶
The shapesDemoTutorial
configuration in RTI_WEB_INTEGRATION_SERVICE.xml
also contains an application called ShapesDemoApp
. This application
creates a single DomainParticipant called MyParticipant
using
the MyDomainLibrary::ShapeDomain
domain. This significantly reduces
the entities that need to be defined (i.e., we do not need to
register ShapeType
or create the Square
topic). MyParticipant
creates both a Publisher and a Subscriber,
which create a Square
DataWriter, and a Square
DataReader,
respectively.
Here is the XML representation of ShapesDemo
as defined in RTI_WEB_INTEGRATION_SERVICE.xml
:
<web_integration_service name="shapesDemoTutorial">
<application name="ShapesDemoApp">
<domain_participant name="MyParticipant"
domain_ref="ShapesDomainLibrary::ShapesDomain">
<publisher name="MyPublisher">
<data_writer name="MySquareWriter" topic_ref="Square" />
</publisher>
<subscriber name="MySubscriber">
<data_reader name="MySquareReader" topic_ref="Square" />
</subscriber>
</domain_participant>
</application>
</web_integration_service>
To load the whole system definition, start Web Integration Service and
specify the shapesDemoTutorial
configuration, like this:
$NDDSHOME/bin/rtiwebintegrationservice -cfgName shapesDemoTutorial
Web Integration Service will instantiate all the applications
under shapesDemoTutorial
and their contained entities. You can check that
the MyParticipant
has been created by calling GET
on /applications/ShapesDemoApp/domain_participants
:
GET /dds/rest1/applications/ShapesDemoApp/domain_participants HTTP/1.1
Host: <host>[:<port>]
Cache-Control: no-cache
curl -X GET -H "Cache-Control:no-cache" http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants
6.2.3.1. Sending and Receiving Square Topics¶
Sending a Square
You can use the instantiated DataWriter to start writing Square
samples. The XML representation of a ShapeType
data sample follows
this structure:
<data>
<color>YELLOW</color>
<x>100</x>
<y>150</y>
<shapesize>30</shapesize>
</data>
To write a new data sample, do a POST
on /applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers/MySquareWriter
and pass in the XML representation of the data sample:
POST /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers/MySquareWriter HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 110
Cache-Control: no-cache
<data>
<color>YELLOW</color>
<x>100</x>
<y>150</y>
<shapesize>30</shapesize>
</data>
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<data>
<color>YELLOW</color>
<x>100</x>
<y>150</y>
<shapesize>30</shapesize>
</data>' http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers/MySquareWriter
If you subscribe to Squares on Domain 0 using RTI Shapes Demo and publish the sample again, you should see a new yellow square in position (100,150).
Receiving Squares
To read samples using Web Integration Service, call GET
on /applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers/MySquareReader
:
GET /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers/MySquareReader HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Cache-Control: no-cache
curl -X GET -H "Cache-Control:no-cache" http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers/MySquareReader
Response
HTTP/1.1 200 Samples read
Content-Type: application/dds-web+xml
Cache-Control: no-cache
Content-Length: 528
Date: Fri, 04 Mar 2016 18:52:45 GMT
<read_sample_seq>
<sample>
<read_sample_info>
<source_timestamp>
<sec>1457117555</sec>
<nanosec>247519000</nanosec>
</source_timestamp>
<valid_data>true</valid_data>
<instance_handle>
9ED0E8B29F0249BECF6B24567D3B0DA9
</instance_handle>
<instance_state>ALIVE</instance_state>
<sample_state>NOT_READ</sample_state>
<view_state>NEW</view_state>
</read_sample_info>
<data>
<color>YELLOW</color>
<x>100</x>
<y>150</y>
<shapesize>30</shapesize>
</data>
</sample>
</read_sample_seq>
6.2.4. Creating New Topics, DataWriters, and DataReaders¶
Sometimes you may want to create new DataWriters and DataReaders
for sending and receiving new Topics. For instance, with the current
configuration our ShapesDemoApp
application can only send and
receive Square
topics. This section explains how to add new Topics,
DataWriters, and DataReaders to our ShapesDemoApp
application to
be able to send and receive Circles
and Triangles
as well.
6.2.5. Creating New Topics¶
6.2.5.1. Creating a Circle¶
To create a new Circle
Topic, call POST
on /applications/ShapesDemoApp/domain_participants/MyParticipant/topics
and pass in the XML representation of the Topic in the HTTP request. Note
that since ShapeType
is already registered, you do not need to register
it again.
POST /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/topics HTTP/1.1
Host: <host>[:<port>]
Content-Length: 52
Content-Type: application/dds-web+xml
Cache-Control: no-cache
<topic name="Circle" register_type_ref="ShapeType"/>
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<topic name="Circle" register_type_ref="ShapeType"/>' http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/topics
6.2.5.2. Creating a Triangle¶
To create a Triangle
topic, call POST
on /applications/ShapesDemoApp/domain_participants/MyParticipant/topics
and pass in the XML representation of the Topic in the HTTP request:
POST /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/topics HTTP/1.1
Host: <host>[:<port>]
Content-Length: 54
Content-Type: application/dds-web+xml
Cache-Control: no-cache
<topic name="Triangle" register_type_ref="ShapeType"/>
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<topic name="Triangle" register_type_ref="ShapeType"/>' http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/topics
6.2.6. Creating New DataWriters and DataReaders¶
Once you have created the Circle
and Triangle
Topics, you can
create DataWriters and DataReaders for each Topic by calling POST
on /applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers
and /applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers
, respectively,
and passing in their XML representations in the body of the HTTP request.
6.2.6.1. Creating a Circle DataWriter¶
POST /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 56
Cache-Control: no-cache
<data_writer name="MyCircleWriter" topic_ref="Circle" />
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<data_writer name="MyCircleWriter" topic_ref="Circle" />' http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers
6.2.6.2. Creating a Triangle DataWriter¶
POST /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers HTTP/1.1
Host: <host>[:<port>]
Content-Length: 60
Content-Type: application/dds-web+xml
Cache-Control: no-cache
<data_writer name="MyTriangleWriter" topic_ref="Triangle" />
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<data_writer name="MyTriangleWriter" topic_ref="Triangle" />' http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers
6.2.6.3. Creating a Circle DataReader¶
POST /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 52
Cache-Control: no-cache
<data_reader name="MyCircleReader" topic_ref="Circle"/>
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<data_reader name="MyCircleReader" topic_ref="Circle"/>' http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers
6.2.6.4. Creating a Triangle DataReader¶
POST /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 55
Cache-Control: no-cache
<data_reader name="MyTriangleReader" topic_ref="Triangle/>
curl -X POST -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" -d '<data_reader name="MyTriangleReader" topic_ref="Triangle"/>' http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers
6.2.6.5. Listing New DataReaders and DataWriters¶
You can check whether the new DataWriters and DataReaders were successfully created by calling GET
on their respective resource URLs:
Listing DataWriters
GET /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Cache-Control: no-cache
curl -X GET -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/publishers/MyPublisher/data_writers
Listing DataReaders
GET /dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Cache-Control: no-cache
curl -X GET -H "Content-Type:application/dds-web+xml" -H "Cache-Control:no-cache" http://<host>[:<port>]/dds/rest1/applications/ShapesDemoApp/domain_participants/MyParticipant/subscribers/MySubscriber/data_readers
Responses
<data_writer_list>
<data_writer name="MySquareWriter" />
<data_writer name="MyCircleWriter" />
<data_writer name="MyTriangleWriter" />
</data_writer_list>
<data_reader_list>
<data_reader name="MySquareReader" />
<data_reader name="MyCircleReader" />
<data_reader name="MyTriangleReader" />
</data_reader_list>
6.3. More Complex Example¶
This example shows you how to send and receive samples of more complex data types. We will show you how to write nested structures, sequences, arrays, and enums. We will also explain how to create QoS libraries and QoS profiles to configure QoS settings for different DDS entities.
Just like we did in the Hello World example in Section 6.1, we will start a new instance of Web Integration Service from an empty configuration.
$NDDSHOME/bin/rtiwebintegrationservice -cfgName default
6.3.1. Types Definition¶
In this example we define a much more complicated type called ComplexType
.
To load ComplexType
, call POST
on /types
, passing its XML definition
in the body of the HTTP request.
POST /dds/rest1/types HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 2475
Cache-Control: no-cache
<types>
<const name="MAX_COLOR_LEN" type="long" value="255" />
<typedef name="MYBOOL" type="boolean" />
<enum name="MyEnum">
<enumerator name="ACE" value="1" />
<enumerator name="KING" value="13" />
<enumerator name="QUEEN" value="12" />
</enum>
<struct name="PrimitivesType">
<member name="aString" type="string" stringMaxLength="MAX_COLOR_LEN" />
<member name="aLong" type="long" />
<member name="aShort" type="short" />
<member name="aUnsignedShort" type="unsignedShort" />
<member name="aUnsignedLong" type="unsignedLong" />
<member name="aFloat" type="float" />
<member name="aDouble" type="double" />
<member name="aBoolean" type="boolean" />
<member name="aChar" type="char" />
<member name="aWchar" type="wchar" />
<member name="aLongLong" type="longLong" />
<member name="aUnsignedLongLong" type="unsignedLongLong" />
<member name="anEnum" type="nonBasic" nonBasicTypeName="MyEnum" />
<member sequenceMaxLength="3" name="anEnumSeq" type="nonBasic"
nonBasicTypeName="MyEnum" />
<member arrayDimensions="3" name="anEnumArr" type="nonBasic"
nonBasicTypeName="MyEnum" />
</struct>
<struct name="ComplexType">
<member name="aString" type="string" stringMaxLength="MAX_COLOR_LEN" />
<member name="aLong" type="long" />
<member name="aShort" type="short" />
<member name="anOctet" type="octet" />
<member name="aUnsignedShort" type="unsignedShort" />
<member name="aUnsignedLong" type="unsignedLong" />
<member name="aFloat" type="float" />
<member name="aDouble" type="double" />
<member name="aBoolean" type="boolean" />
<member name="aChar" type="char" />
<member name="aWchar" type="wchar" />
<member name="aLongLong" type="longLong" />
<member name="aUnsignedLongLong" type="unsignedLongLong" />
<member name="anAlias" type="nonBasic" nonBasicTypeName="MYBOOL" />
<member name="aComplexType" type="nonBasic" nonBasicTypeName="PrimitivesType" />
<member name="anEnum" type="nonBasic" nonBasicTypeName="MyEnum" />
<member sequenceMaxLength="3" name="anEnumSeq" type="nonBasic"
nonBasicTypeName="MyEnum" />
<member arrayDimensions="3" name="anEnumArr" type="nonBasic"
nonBasicTypeName="MyEnum" />
</struct>
</types>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<types>
<const name="MAX_COLOR_LEN" type="long" value="255"/>
<typedef name="MYBOOL" type="boolean"/>
<enum name="MyEnum">
<enumerator name="ACE" value="1"/>
<enumerator name="KING" value="13"/>
<enumerator name="QUEEN" value="12"/>
</enum>
<struct name="PrimitivesType">
<member name="aString" type="string" stringMaxLength="MAX_COLOR_LEN"/>
<member name="aLong" type="long"/>
<member name="aShort" type="short"/>
<member name="aUnsignedShort" type="unsignedShort"/>
<member name="aUnsignedLong" type="unsignedLong"/>
<member name="aFloat" type="float"/>
<member name="aDouble" type="double"/>
<member name="aBoolean" type="boolean"/>
<member name="aChar" type="char"/>
<member name="aWchar" type="wchar"/>
<member name="aLongLong" type="longLong"/>
<member name="aUnsignedLongLong" type="unsignedLongLong"/>
<member name="anEnum" type="nonBasic" nonBasicTypeName="MyEnum"/>
<member sequenceMaxLength="3" name="anEnumSeq" type="nonBasic"
nonBasicTypeName="MyEnum"/>
<member arrayDimensions="3" name="anEnumArr" type="nonBasic"
nonBasicTypeName="MyEnum"/>
</struct>
<struct name="ComplexType">
<member name="aString" type="string" stringMaxLength="MAX_COLOR_LEN"/>
<member name="aLong" type="long"/>
<member name="aShort" type="short"/>
<member name="anOctet" type="octet"/>
<member name="aUnsignedShort" type="unsignedShort"/>
<member name="aUnsignedLong" type="unsignedLong"/>
<member name="aFloat" type="float"/>
<member name="aDouble" type="double"/>
<member name="aBoolean" type="boolean"/>
<member name="aChar" type="char"/>
<member name="aWchar" type="wchar"/>
<member name="aLongLong" type="longLong"/>
<member name="aUnsignedLongLong" type="unsignedLongLong"/>
<member name="anAlias" type="nonBasic" nonBasicTypeName="MYBOOL"/>
<member name="aComplexType" type="nonBasic" nonBasicTypeName="PrimitivesType"/>
<member name="anEnum" type="nonBasic" nonBasicTypeName="MyEnum"/>
<member sequenceMaxLength="3" name="anEnumSeq" type="nonBasic"
nonBasicTypeName="MyEnum"/>
<member arrayDimensions="3" name="anEnumArr" type="nonBasic"
nonBasicTypeName="MyEnum"/>
</struct>
</types>' http://<host>[:<port>]/dds/rest1/types
6.3.2. QoS Libraries and QoS Profiles Definition¶
The QoS section of the XML file provides a way to define QoS libraries and QoS profiles that can be used to configure different QoS settings in your applications.
In this example, we create a QoS library with an empty QoS profile to
provide a placeholder in which QoS settings can be specified. Using this
empty profile results in the default DDS QoS being used. To create a new
QoS library, call POST
on /qos_libraries
and pass in its XML
representation in the body of the HTTP request:
POST /dds/rest1/qos_libraries HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 105
Cache-Control: no-cache
<qos_library name="qosLibrary">
<qos_profile name="DefaultProfile">
</qos_profile>
</qos_library>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<qos_library name="qosLibrary">
<qos_profile name="DefaultProfile">
</qos_profile>
</qos_library>' http://<host>[:<port>]/dds/rest1/qos_libraries
To create a new QoS profile within the created QoS library, call POST
on /qos_libraries/qosLibrary/qos_profiles
and pass in its XML
representation in the body of the HTTP request.
POST /dds/rest1/qos_libraries/qosLibrary/qos_profiles HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 50
Cache-Control: no-cache
<qos_profile name="AnotherProfile">
</qos_profile>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<qos_profile name="AnotherProfile">
</qos_profile>' http://<host>[:<port>]/dds/rest1/qos_libraries/qosLibrary/qos_profiles
6.3.3. Application Definition¶
6.3.3.1. Creating Applications¶
To illustrate the creation of DDS entities using separate requests, let’s create an empty application to which we will add subsequent elements.
POST /dds/rest1/applications HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 40
Cache-Control: no-cache
<application name="ComplexApplication"/>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<application name="ComplexApplication"/>' http://<host>[:<port>]/dds/rest1/applications
6.3.3.2. Creating DomainParticipants¶
We are going to create two DomainParticipants within
ComplexApplication
: DefaultParticipant
and SHMEMParticipant
.
Each participant inherits from a different QoS profile using the
base_name
attribute of the <participant_qos>
tag.
Note that base_name
takes the fully qualified name of the QoS
profile, i.e., <qos_library>::<qos_profile>
.
You can override these values by specifying different QoS settings within
the <participant_qos>
tag. In this example, we override the value
of TransportBuiltinQosPolicy to specify the transports that
DomainParticipants register automatically when they are enabled.
Creating DefaultParticipant
POST /dds/rest1/applications/ComplexApplication/domain_participants HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 248
Cache-Control: no-cache
<domain_participant name="DefaultParticipant">
<participant_qos base_name="qosLibrary::DefaultProfile">
<transport_builtin>
<mask>UDPv4 | SHMEM</mask>
</transport_builtin>
</participant_qos>
</domain_participant>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<domain_participant name="DefaultParticipant">
<participant_qos base_name="qosLibrary::DefaultProfile">
<transport_builtin>
<mask>UDPv4 | SHMEM</mask>
</transport_builtin>
</participant_qos>
</domain_participant>' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants
Creating SHMEMParticipant
POST /dds/rest1/applications/ComplexApplication/domain_participants HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 238
Cache-Control: no-cache
<domain_participant name="SHMEMParticipant">
<participant_qos base_name="qosLibrary::AnotherProfile">
<transport_builtin>
<mask>SHMEM</mask>
</transport_builtin>
</participant_qos>
</domain_participant>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<domain_participant name="SHMEMParticipant">
<participant_qos base_name="qosLibrary::AnotherProfile">
<transport_builtin>
<mask>SHMEM</mask>
</transport_builtin>
</participant_qos>
</domain_participant>' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants
6.3.3.3. Deleting DomainParticipants¶
In the rest of the example we will only be using
DefaultParticipant
, so we can delete the SHMEMParticipant
we just created:
DELETE /dds/rest1/applications/ComplexApplication/domain_participants/SHMEMParticipant HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Cache-Control: no-cache
curl -X DELETE -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants/SHMEMParticipant
6.3.3.4. Registering Types¶
Before creating Topics and other DDS entities, we need to
register ComplexType
.
POST /dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/registered_types HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 57
Cache-Control: no-cache
<register_type name="ComplexType" type_ref="ComplexType"/>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<register_type name="ComplexType" type_ref="ComplexType"/>' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/registered_types
6.3.3.5. Creating Topics¶
Now we are going to create a ComplexTopic
associated
with ComplextType
. Call POST
on
/applications/ComplexApplication/domain_participants/DefaultParticipant
/topics
and pass in the XML representation of the Topic in the body
of the HTTP request. In this case we will modify <topic_qos>
to
set the ReliabilityQosPolicy kind to RELIABLE_RELIABILITY_QOS
:
POST /dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/topics HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 235
Cache-Control: no-cache
<topic register_type_ref="ComplexType" name="ComplexTopic">
<topic_qos base_name="qosLibrary::DefaultProfile">
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
</topic_qos>
</topic>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<topic register_type_ref="ComplexType" name="ComplexTopic">
<topic_qos base_name="qosLibrary::DefaultProfile">
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
</topic_qos>
</topic>' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/topics
6.3.3.6. Creating Publishers¶
To create a new Publisher within DefaultParticipant
, call
POST
on
/applications/ComplexApplication/domain_participants/DefaultParticipant/publishers
and pass in its XML representation in the body of the HTTP request:
POST /dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/publishers HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 36
Cache-Control: no-cache
<publisher name="ComplexPublisher"/>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<publisher name="ComplexPublisher"/>' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/publishers
6.3.3.7. Creating DataWriters¶
To create a DataWriter of ComplexTopic
, call POST
on
/applications/ComplexApplication/domain_participants/DefaultParticipant/publishers/ComplexPublisher/data_writers
and pass in its XML representation in the body of the HTTP request. In this case we will modify the DataWriter
QoS and set the ReliabilityQosPolicy kind to RELIABLE_RELIABILITY_QOS
:
POST /dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/publishers/ComplexPublisher/data_writers HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 247
Cache-Control: no-cache
<data_writer topic_ref="ComplexTopic" name="ComplexDW">
<datawriter_qos base_name="qosLibrary::AnotherProfile">
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
</datawriter_qos>
</data_writer>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<data_writer topic_ref="ComplexTopic" name="ComplexDW">
<datawriter_qos base_name="qosLibrary::AnotherProfile">
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
</datawriter_qos>
</data_writer>' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/publishers/ComplexPublisher/data_writers
6.3.3.8. Creating Subscribers¶
To create a new Subscriber within DefaultParticipant
, call
POST
on
/applications/ComplexApplication/domain_participants/DefaultParticipant/subscribers
and pass in its XML representation in the body of the HTTP request:
POST /dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/subscribers HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 38
Cache-Control: no-cache
<subscriber name="ComplexSubscriber"/>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<subscriber name="ComplexSubscriber"/>' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/subscribers
6.3.3.9. Creating DataReaders¶
To create a DataReader of ComplexTopic
, call POST
on
/applications/ComplexApplication/domain_participants/DefaultParticipant/subscribers/ComplexSubscriber/data_readers
and pass in its XML representation in the body of the HTTP request. In this case we will modify the
DataReader QoS and set the ReliabilityQosPolicy kind to RELIABLE_RELIABILITY_QOS
:
POST /dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/subscribers/ComplexSubscriber/data_readers HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 276
Cache-Control: no-cache
<data_reader topic_ref="ComplexTopic" name="ComplexDR">
<datareader_qos>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<history>
<depth>10</depth>
</history>
</datareader_qos>
</data_reader>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<data_reader topic_ref="ComplexTopic" name="ComplexDR">
<datareader_qos>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<history>
<depth>10</depth>
</history>
</datareader_qos>
</data_reader>
' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/subscribers/ComplexSubscriber/data_readers
6.3.4. Sending and Receiving Complex Samples¶
6.3.4.1. Sending Samples¶
Once the DataWriter is available, you can start writing
ComplexType
data samples. The XML representation of a
ComplexType
data sample follows the structure of the previous
examples, but introduces the concept of complex members (e.g., nested
structs, sequences, or arrays). We also introduce the concept of enums.
Note that when writing enums you need to provide the integer
representation of the enumeration value.
To write a new ComplexType
data sample, POST
the XML sample
representation on /applications/ComplexApplication/domain_participants/DefaultParticipant/publishers/ComplexPublisher/data_writers/ComplexDW
.
POST /dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/publishers/ComplexPublisher/data_writers/ComplexDW HTTP/1.1
Host: <host>[:<port>]
Content-Type: application/dds-web+xml
Content-Length: 1296
Cache-Control: no-cache
<data>
<aString>This is a string!</aString>
<aLong>-123456789</aLong>
<aShort>125</aShort>
<anOctet>255</anOctet>
<aUnsignedShort>5</aUnsignedShort>
<aUnsignedLong>123456789</aUnsignedLong>
<aFloat>3.14</aFloat>
<aDouble>3.1592</aDouble>
<aBoolean>false</aBoolean>
<aChar>a</aChar>
<aWchar>~</aWchar>
<aLongLong>-4215479752654469884268442</aLongLong>
<aUnsignedLongLong>14</aUnsignedLongLong>
<anEnumSeq>
<item>KING</item>
<item>QUEEN</item>
<item>ACE</item>
</anEnumSeq>
<anEnumArr>
<item>ACE</item>
<item>QUEEN</item>
<item>KING</item>
</anEnumArr>
<aComplexType>
<aString>Another string!</aString>
<aLong>-123456789</aLong>
<aShort>125</aShort>
<aUnsignedShort>5</aUnsignedShort>
<aUnsignedLong>123456789</aUnsignedLong>
<aFloat>3.14</aFloat>
<aDouble>3.1592</aDouble>
<aBoolean>true</aBoolean>
<aChar>a</aChar>
<aWchar>~</aWchar>
<aLongLong>-4215479752654469884268442</aLongLong>
<aUnsignedLongLong>21</aUnsignedLongLong>
<anEnumSeq>
<item>KING</item>
<item>QUEEN</item>
<item>ACE</item>
</anEnumSeq>
<anEnumArr>
<item>ACE</item>
<item>QUEEN</item>
<item>KING</item>
</anEnumArr>
</aComplexType>
<anEnum>12</anEnum>
</data>
curl -X POST -H "Content-Type: application/dds-web+xml" -H "Cache-Control: no-cache" -d '<data>
<aString>This is a string!</aString>
<aLong>-123456789</aLong>
<aShort>125</aShort>
<anOctet>255</anOctet>
<aUnsignedShort>5</aUnsignedShort>
<aUnsignedLong>123456789</aUnsignedLong>
<aFloat>3.14</aFloat>
<aDouble>3.1592</aDouble>
<aBoolean>false</aBoolean>
<aChar>a</aChar>
<aWchar>~</aWchar>
<aLongLong>-4215479752654469884268442</aLongLong>
<aUnsignedLongLong>14</aUnsignedLongLong>
<anEnumSeq>
<item>KING</item>
<item>QUEEN</item>
<item>ACE</item>
</anEnumSeq>
<anEnumArr>
<item>ACE</item>
<item>QUEEN</item>
<item>KING</item>
</anEnumArr>
<aComplexType>
<aString>Another string!</aString>
<aLong>-123456789</aLong>
<aShort>125</aShort>
<aUnsignedShort>5</aUnsignedShort>
<aUnsignedLong>123456789</aUnsignedLong>
<aFloat>3.14</aFloat>
<aDouble>3.1592</aDouble>
<aBoolean>true</aBoolean>
<aChar>a</aChar>
<aWchar>~</aWchar>
<aLongLong>-4215479752654469884268442</aLongLong>
<aUnsignedLongLong>21</aUnsignedLongLong>
<anEnumSeq>
<item>KING</item>
<item>QUEEN</item>
<item>ACE</item>
</anEnumSeq>
<anEnumArr>
<item>ACE</item>
<item>QUEEN</item>
<item>KING</item>
</anEnumArr>
</aComplexType>
<anEnum>12</anEnum>
</data>' http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/publishers/ComplexPublisher/data_writers/ComplexDW
6.3.4.2. Receiving Samples¶
Request
To read samples, call `GET`
on
/applications/ComplexApplication/domain_participants/DefaultParticipant/subscribers/ComplexSubscriber/data_readers/ComplexDR
:
GET /dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/subscribers/ComplexSubscriber/data_readers/ComplexDR HTTP/1.1
Host: <host>[:<port>]
Cache-Control: no-cache
curl -X GET -H "Cache-Control: no-cache" http://<host>[:<port>]/dds/rest1/applications/ComplexApplication/domain_participants/DefaultParticipant/subscribers/ComplexSubscriber/data_readers/ComplexDR
Response
The response contains the sequence of read samples, including sample information and sample data:
HTTP/1.1 200 Samples read
Content-Type: application/dds-web+xml
Cache-Control: no-cache
Content-Length: 1535
Date: Fri, 04 Mar 2016 19:00:36 GMT
<read_sample_seq>
<sample>
<read_sample_info>
<source_timestamp>
<sec>1457118026</sec>
<nanosec>979762998</nanosec>
</source_timestamp>
<valid_data>true</valid_data>
<instance_handle>
00000000000000000000000000000000
</instance_handle>
<instance_state>ALIVE</instance_state>
<sample_state>NOT_READ</sample_state>
<view_state>NEW</view_state>
</read_sample_info>
<data>
<aString>This is a string!</aString>
<aLong>-123456789</aLong>
<aShort>125</aShort>
<anOctet>255</anOctet>
<aUnsignedShort>5</aUnsignedShort>
<aUnsignedLong>123456789</aUnsignedLong>
<aFloat>3.140000</aFloat>
<aDouble>3.159200</aDouble>
<aBoolean>false</aBoolean>
<aChar>a</aChar>
<aWchar>~</aWchar>
<aLongLong>-9223372036854775808</aLongLong>
<aUnsignedLongLong>14</aUnsignedLongLong>
<anAlias>false</anAlias>
<aComplexType>
<aString>Another string!</aString>
<aLong>-123456789</aLong>
<aShort>125</aShort>
<aUnsignedShort>5</aUnsignedShort>
<aUnsignedLong>123456789</aUnsignedLong>
<aFloat>3.140000</aFloat>
<aDouble>3.159200</aDouble>
<aBoolean>true</aBoolean>
<aChar>a</aChar>
<aWchar>~</aWchar>
<aLongLong>-9223372036854775808</aLongLong>
<aUnsignedLongLong>21</aUnsignedLongLong>
<anEnum>1</anEnum>
<anEnumSeq>
<item>KING</item>
<item>QUEEN</item>
<item>ACE</item>
</anEnumSeq>
<anEnumArr>
<item>ACE</item>
<item>QUEEN</item>
<item>KING</item>
</anEnumArr>
</aComplexType>
<anEnum>12</anEnum>
<anEnumSeq>
<item>KING</item>
<item>QUEEN</item>
<item>ACE</item>
</anEnumSeq>
<anEnumArr>
<item>ACE</item>
<item>QUEEN</item>
<item>KING</item>
</anEnumArr>
</data>
</sample>
</read_sample_seq>
6.4. Simple JavaScript Client Application¶
This example illustrates how to subscribe to DDS data with a simple JavaScript application running in a browser. In particular, the example implements a simplified version of RTI Shapes Demo where samples are drawn on a canvas using Fabric—a simple JavaScript framework.
The example code can be found under
<path_to_examples>/web_integration_service/examples/simple_shapes_demo
.
Note
See Section 1.2 to learn about
the location of <path_to_examples>
on your platform.
6.4.1. Running the Example¶
To run the example, open a terminal and enter the following command:
$NDDSHOME/bin/rtiwebintegrationservice \
-cfgFile $path_to_examples/web_integration_service/examples/simple_shapes_demo/simple_shapes_demo.xml \
-cfgName simpleShapesDemo \
-documentRoot $path_to_examples/web_integration_service \
-enableKeepAlive yes
Where:
- The
-cfgFile
argument loads the appropriate configuration file into Web Integration Service. - The
-cfgName
argument specifies the configuration to be instantiated—in this casesimpleShapesDemo
—which starts theShapesDemoApp
. This application instantiates a DomainParticipant with DataReaders to read to all shape topics (i.e., Squares, Circles, and Triangles). - The
-documentRoot
argument specifies the folder that Web Integration Service’s web server will provide when accessing the default URL. That ishttp://<host>:8080
. This specific example can then be found underhttp://<hostname>:8080/examples/simple_shapes_demo/js
. - The
-enablekeepAlive
argument configures the service to keep open the underlying TCP connection between client and server between subsequent requests and responses when possible.
6.4.1.1. Running RTI Shapes Demo¶
Once you have started Web Integration Service, you can open RTI Shapes Demo and start publishing shapes on Domain 0.
6.4.1.2. Running Simple Shapes Demo JavaScript Client¶
Open a browser and navigate to http://<host>:8080/examples/simple_shapes_demo/js
.
There you will find all the shapes that are being published.
6.4.2. Example Code¶
6.4.2.1. Client Application¶
/*
* (c) 2016-2017 Copyright, Real-Time Innovations, Inc. All rights reserved.
* RTI grants Licensee a license to use, modify, compile, and create derivative
* works of the Software. Licensee has the right to distribute object form
* only for use with RTI products. The Software is provided "as is", with no
* warranty of any type, including any warranty for fitness for any purpose.
* RTI is under no obligation to maintain or support the Software. RTI shall
* not be liable for any incidental or consequential damages arising out of the
* use or inability to use the software.
*/
var rti = rti || {};
/**
* @namespace rti.shapesdemo
*/
rti.shapesdemo = {
/**
* Sets up a new canvas in a <div id="shapesDemoCanvas">. This method
* needs to be called before reading or drawing shapes.
*/
setupScenario: function() {
rti.shapesdemo.canvas = new fabric.Canvas(
'shapesDemoCanvas',
{
hoverCursor: 'pointer',
perPixelTargetFind: true,
targetFindTolerance: 5,
backgroundImage: '../../../../resources/img/rti_background.png'
}
);
},
/**
* Sets up the enviroment for reading shapes. The method will call the
* methods that draw shapes at 33 ms intervals.
*/
readShapes: function() {
var squareReaderUrl =
"/dds/rest1/applications/ShapesDemoApp" +
"/domain_participants/MyParticipant" +
"/subscribers/MySubscriber" +
"/data_readers/MySquareReader";
var triangleReaderUrl =
"/dds/rest1/applications/ShapesDemoApp" +
"/domain_participants/MyParticipant" +
"/subscribers/MySubscriber" +
"/data_readers/MyTriangleReader";
var circleReaderUrl =
"/dds/rest1/applications/ShapesDemoApp" +
"/domain_participants/MyParticipant" +
"/subscribers/MySubscriber" +
"/data_readers/MyCircleReader";
var shapesDemoIntervalPeriod = 33; // in milliseconds
// Call drawShape() for Squares, Circles, and Triangles every
// shapesDemoIntervalPeriod, passing the resulting data
// for reading new samples of the appropriate topic in json format
// without deleting the samples from the Reader's cache.
setInterval(function(){
// Read Squares
$.getJSON(
squareReaderUrl,
{
sampleFormat: "json",
removeFromReaderCache: "false"
},
function(data) {
rti.shapesdemo.drawShape(data, "Square");
}
);
// Read Triangles
$.getJSON(
triangleReaderUrl,
{
sampleFormat: "json",
removeFromReaderCache: "false"
},
function(data) {
rti.shapesdemo.drawShape(data, "Triangle");
}
);
// Read Circles
$.getJSON(
circleReaderUrl,
{
sampleFormat: "json",
removeFromReaderCache: "false"
},
function(data) {
rti.shapesdemo.drawShape(data, "Circle");
}
);
}, shapesDemoIntervalPeriod);
},
/**
* Draws a sequence of shapes given their shape kind (i.e., whether it is
* a Circle, Square, or a Triangle).
* @param sampleSeq Sequence of samples to be drawn.
* @param shapeKind kind of shape to draw. Valid values are 'Circle',
* 'Square', or 'Triangle'.
*/
drawShape: function(sampleSeq, shapeKind) {
sampleSeq.forEach(function(sample, i, samples) {
// Process metadata
var validData = sample.read_sample_info.valid_data;
var instanceHandle = sample.read_sample_info.instance_handle;
var instanceState = sample.read_sample_info.instance_state;
// If we received an invalid data sample, and the instance state
// is != ALIVE, then the instance has been either disposed or
// unregistered and we remove the shape from the canvas.
if (!validData) {
if (instanceState != "ALIVE") {
rti.shapesdemo.canvas.getObjects().every(
function (element, j, array) {
if (element.uid.instanceHandle == instanceHandle
&& element.uid.topic == shapeKind) {
element.remove();
rti.shapesdemo.canvas.renderAll();
return false;
}
return true;
}
);
return true;
}
return true;
}
// Process sample data (i.e., color, shapesSize, and position
// of the received shape). If the color is not in the list of
// supported colors, we assign it blue.
var color;
if (rti.shapesdemo.shapeColors.hasOwnProperty(sample.data.color)) {
color = rti.shapesdemo.shapeColors[sample.data.color];
} else {
color = rti.shapesdemo.shapeColors.BLUE;
}
var shapeSize = sample.data.shapesize;
var x = sample.data.x - shapeSize/2;
var y = sample.data.y - shapeSize/2;
// Look for the shape received on the canvas
var shape = undefined;
for (var i = 0; i < rti.shapesdemo.canvas.getObjects().length; i++){
var currentElement = rti.shapesdemo.canvas.getObjects()[i];
if (currentElement.uid.instanceHandle == instanceHandle
&& currentElement.uid.topic == shapeKind) {
shape = currentElement;
break;
}
}
// If it is not there, we need to create a new shape in the
// received position. Otherwise, update the existing shape's
// position.
if (shape == undefined) { // Add new shape in the position
var newShape;
if (shapeKind == "Square") {
newShape = new fabric.Rect({
left: x,
top: y,
originX: 'left',
originY: 'top',
width: shapeSize,
height: shapeSize,
angle: 0,
fill: color,
transparentCorners: false,
selectable: false
});
} else if (shapeKind == "Triangle") {
newShape = new fabric.Triangle({
left: x,
top: y,
originX: 'left',
originY: 'top',
width: shapeSize,
height: shapeSize,
angle: 0,
fill: color,
transparentCorners: false,
selectable: false
});
} else if (shapeKind == "Circle"){
newShape = new fabric.Circle({
left: x,
top: y,
originX: 'left',
originY: 'top',
radius: shapeSize/2,
angle: 0,
fill: color,
transparentCorners: false,
selectable: false
});
}
newShape.uid = {
"instanceHandle": instanceHandle,
"topic": shapeKind
}
rti.shapesdemo.canvas.add(newShape);
} else { // Update position of existing shape
shape.setLeft(x).setCoords();
shape.setTop(y).setCoords();
rti.shapesdemo.canvas.renderAll();
}
return true;
});
}
}
/**
* Canvas in which we will be drawing all the shapes
*/
rti.shapesdemo.canvas = {};
/**
* Object with the list of supported colors along with their corresponding
* color code.
*/
rti.shapesdemo.shapeColors = {
PURPLE : "#b000ff",
BLUE: "#0000ff",
RED: "#ff0000",
GREEN: "#00ff00",
YELLOW: "#ffff00",
CYAN: "#00ffff",
MAGENTA: "#ff00ff",
ORANGE: "#ff8200"
};
6.4.2.2. Web Integration Service Configuration File¶
<?xml version="1.0"?>
<!--
(c) 2016 Copyright, Real-Time Innovations, Inc. All rights reserved.
RTI grants Licensee a license to use, modify, compile, and create derivative
works of the Software. Licensee has the right to distribute object form only
for use with RTI products. The Software is provided "as is", with no warranty
of any type, including any warranty for fitness for any purpose. RTI is under
no obligation to maintain or support the Software. RTI shall not be liable for
any incidental or consequential damages arising out of the use or inability to
use the software.
-->
<!-- RTI Data Distribution Service Deployment -->
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/latest/rti_web_integration_service.xsd">
<!-- This QoS Profile enables a reliable DataReader that will keep only
the last sample in its cache.
-->
<qos_library name="SimpleShapesDemoQoSLib">
<qos_profile name="SimpleShapesDemoQosProfile" is_default_qos="true">
<datareader_qos>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<history>
<depth>10</depth>
<kind>KEEP_LAST_HISTORY_QOS</kind>
</history>
</datareader_qos>
</qos_profile>
</qos_library>
<!--
This configuration contains a complete scenario for interacting with RTI
Shapes Demo. That is, it creates all the necessary Topics, DataWriters,
and DataReaders to publish and subscribe to Squares, Circles, and
Triangles. The data types and domains in "MyParticipant" refer to the
ones defined in resource/xml/RTI_WEB_INTEGRATION_SERVICE.xml.
Note that this file is automatically loaded by Web Integration Service
at startup.
-->
<web_integration_service name="simpleShapesDemo">
<application name="ShapesDemoApp">
<domain_participant name="MyParticipant"
domain_ref="ShapesDomainLibrary::ShapesDomain">
<register_type name="ShapeType" type_ref="ShapeType" />
<topic name="Square" register_type_ref="ShapeType" />
<topic name="Circle" register_type_ref="ShapeType" />
<topic name="Triangle" register_type_ref="ShapeType" />
<publisher name="MyPublisher">
<data_writer name="MySquareWriter" topic_ref="Square" />
<data_writer name="MyCircleWriter" topic_ref="Circle" />
<data_writer name="MyTriangleWriter" topic_ref="Triangle" />
</publisher>
<subscriber name="MySubscriber">
<data_reader name="MySquareReader" topic_ref="Square" />
<data_reader name="MyCircleReader" topic_ref="Circle" />
<data_reader name="MyTriangleReader" topic_ref="Triangle" />
</subscriber>
</domain_participant>
</application>
</web_integration_service>
</dds>