Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add request-reply example for Python #599

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/connext_dds/request_reply/cs/Primes.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Rti.ConnextDds.RequestReply" Version="7.0.0"/>
<PackageReference Include="Rti.ConnextDds.RequestReply" Version="7.2.0"/>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.21308.1" />
</ItemGroup>

Expand Down
17 changes: 7 additions & 10 deletions examples/connext_dds/request_reply/cs/USER_QOS_PROFILES.xml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<?xml version="1.0"?>

<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/7.0.0/rti_dds_qos_profiles.xsd">
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/7.1.0/rti_dds_qos_profiles.xsd">

<qos_library name="RequestReplyExampleProfiles">

<!-- Default QoS:

This profile contains the QoS that Requesters and Repliers
Expand Down Expand Up @@ -38,15 +37,15 @@
</heartbeats_per_max_samples>
<heartbeat_period>
<sec>0</sec>
<nanosec>100000000</nanosec> <!--100ms -->
<nanosec>100000000</nanosec> <!--100ms -->
</heartbeat_period>
<fast_heartbeat_period>
<sec>0</sec>
<nanosec>10000000</nanosec> <!--10ms -->
<nanosec>10000000</nanosec> <!--10ms -->
</fast_heartbeat_period>
<late_joiner_heartbeat_period>
<sec>0</sec>
<nanosec>10000000</nanosec> <!--10ms -->
<nanosec>10000000</nanosec> <!--10ms -->
</late_joiner_heartbeat_period>
<max_nack_response_delay>
<sec>0</sec>
Expand All @@ -63,7 +62,7 @@

<writer_resource_limits>
<!-- This setting enables efficient communication
between a replier and an arbitrary number of requesters
between a replier and an arbitrary number of requesters
-->
<max_remote_reader_filters>
LENGTH_UNLIMITED
Expand Down Expand Up @@ -99,13 +98,11 @@
</min_heartbeat_response_delay>
</rtps_reliable_reader>
</protocol>

</datareader_qos>

</qos_profile>

<!-- This is the profile used by the Requester.
It inherits from "default", defined above,
<!-- This is the profile used by the Requester.
It inherits from "default", defined above,
and overrides some QoS -->
<qos_profile name="RequesterExampleProfile" base_name="default">

Expand Down
71 changes: 71 additions & 0 deletions examples/connext_dds/request_reply/py/Primes.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*****************************************************************************/
/* (c) Copyright, Real-Time Innovations, All rights reserved. */
/* */
/* Permission to modify and use for internal purposes granted. */
/* This software is provided "as is", without warranty, express or implied. */
/* */
/*****************************************************************************/

/* --- Request type: ------------------------------------------------------- */

/*
* This is the request type.
*
* It simply contains an integer that requests all the prime numbers below it.
*
*/
struct PrimeNumberRequest {
/*
* Requests the calculation of the prime numbers below n
*/
int32 n;

/*
* How many prime numbers should be included in each reply sample.
*
* A smaller value means that results are received more frequently
* (and hence more data samples are sent)
*/
int32 primes_per_reply;
};

/* --- Reply type: --------------------------------------------------------- */

/*
* Indicates the status of one of the multiple possible replies for a request
*/
enum PrimeNumberCalculationStatus {
/*
* Indicates that this reply contains a new sequence of
* prime numbers for a request, but there are still more to come
*/
REPLY_IN_PROGRESS,
/*
* Indicates that this is the last sequence of
* prime numbers for a request.
*/
REPLY_COMPLETED,
/*
* Indicates that there was an error. After an error
* there won't be any more replies for a request
*/
REPLY_ERROR
};

/*
* This is the reply type.
*
* The replier sends sequences of prime numbers as they are being calculated.
*
*/
struct PrimeNumberReply {
/*
* A sequence of prime numbers
*/
sequence<int32> primes;

/*
* Status information about this reply
*/
PrimeNumberCalculationStatus status;
};
41 changes: 41 additions & 0 deletions examples/connext_dds/request_reply/py/Primes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#
# (c) 2023 Copyright, Real-Time Innovations, Inc. All rights reserved.
#
# RTI grants Licensee a license to use, modify, compile, and create derivative
# works of the Software solely 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.
#

# This file was generated by RTI Code Generator with the following command:
# rtiddsgen -language python -unboundedSupport Primes.idl

from dataclasses import field
from typing import Union, Sequence, Optional
import rti.idl as idl
from enum import IntEnum


@idl.struct
class PrimeNumberRequest:
n: idl.int32 = 0
primes_per_reply: idl.int32 = 0


@idl.enum
class PrimeNumberCalculationStatus(IntEnum):
REPLY_IN_PROGRESS = 0
REPLY_COMPLETED = 1
REPLY_ERROR = 2


@idl.struct
class PrimeNumberReply:
primes: Sequence[idl.int32] = field(
default_factory=idl.array_factory(idl.int32)
)
status: PrimeNumberCalculationStatus = (
PrimeNumberCalculationStatus.REPLY_IN_PROGRESS
)
60 changes: 60 additions & 0 deletions examples/connext_dds/request_reply/py/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Example Code: Request-Reply

If you haven't used the RTI Connext Python API before, first check the
[Getting Started Guide](https://community.rti.com/static/documentation/connext-dds/7.0.0/doc/manuals/connext_dds_professional/getting_started_guide/index.html).

## Running the Example

In two separate command prompt windows for the requester and replier run the
following commands from the example directory (this is necessary to ensure the
application loads the QoS defined in *USER_QOS_PROFILES.xml*):

```sh
python primes_replier.py
python primes_requester.py <n>
```

Where ``<n>`` is the number to calculate the primes below.

Use ``-h`` to see the full list of arguments.

## Replier Output

The replier will print a message every time it receives a request, for example:

```plaintext
Calculating prime numbers below 100...
DONE
```

## Requester Output

The requester prints the prime numbers sent by the replier, as they are received.

For example:

```sh
$ python primes_requester.py 100
Sending a request to calculate the prime numbers <= 100 in sequences of 5 or fewer elements
[2, 3, 5, 7, 11]
[13, 17, 19, 23, 29]
[31, 37, 41, 43, 47]
[53, 59, 61, 67, 71]
[73, 79, 83, 89, 97]
DONE
```

Each line of numbers is an individual reply. You can set `--primes-per-reply`
to control this behavior in the example (by default it's 5).

```sh
$ python primes_requester.py 100 --primes-per-reply 10
Running PrimesRequester on domain 0
Sending a request to calculate the prime numbers <= 100 in sequences of 10 or fewer elements
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
[31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
[73, 79, 83, 89, 97]
DONE
```

This demonstrates how a single request can be served by multiple replies.
145 changes: 145 additions & 0 deletions examples/connext_dds/request_reply/py/USER_QOS_PROFILES.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?xml version="1.0"?>

<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/7.1.0/rti_dds_qos_profiles.xsd">

<qos_library name="RequestReplyExampleProfiles">
<!-- Default QoS:

This profile contains the QoS that Requesters and Repliers
would use by default. We can use it as a base profile to inherit
from and override some parameters
-->
<qos_profile name="default">
<datawriter_qos>

<!-- Strict reliable -->
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
<max_blocking_time>
<sec>10</sec>
<nanosec>0</nanosec>
</max_blocking_time>
</reliability>

<history>
<kind>KEEP_ALL_HISTORY_QOS</kind>
</history>

<!-- These are typical protocol parameters for a reliable
DataWriter -->
<protocol>
<rtps_reliable_writer>
<max_heartbeat_retries>
LENGTH_UNLIMITED
</max_heartbeat_retries>
<heartbeats_per_max_samples>
2
</heartbeats_per_max_samples>
<heartbeat_period>
<sec>0</sec>
<nanosec>100000000</nanosec> <!--100ms -->
</heartbeat_period>
<fast_heartbeat_period>
<sec>0</sec>
<nanosec>10000000</nanosec> <!--10ms -->
</fast_heartbeat_period>
<late_joiner_heartbeat_period>
<sec>0</sec>
<nanosec>10000000</nanosec> <!--10ms -->
</late_joiner_heartbeat_period>
<max_nack_response_delay>
<sec>0</sec>
<nanosec>0</nanosec>
</max_nack_response_delay>
<min_nack_response_delay>
<sec>0</sec>
<nanosec>0</nanosec>
</min_nack_response_delay>
<max_send_window_size>32</max_send_window_size>
<min_send_window_size>32</min_send_window_size>
</rtps_reliable_writer>
</protocol>

<writer_resource_limits>
<!-- This setting enables efficient communication
between a replier and an arbitrary number of requesters
-->
<max_remote_reader_filters>
LENGTH_UNLIMITED
</max_remote_reader_filters>
</writer_resource_limits>
</datawriter_qos>

<datareader_qos>
<!-- Strict reliable -->
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
<max_blocking_time>
<sec>10</sec>
<nanosec>0</nanosec>
</max_blocking_time>
</reliability>

<history>
<kind>KEEP_ALL_HISTORY_QOS</kind>
</history>

<!-- These are typical protocol parameters for a reliable
DataReader -->
<protocol>
<rtps_reliable_reader>
<max_heartbeat_response_delay>
<sec>0</sec>
<nanosec>0</nanosec>
</max_heartbeat_response_delay>
<min_heartbeat_response_delay>
<sec>0</sec>
<nanosec>0</nanosec>
</min_heartbeat_response_delay>
</rtps_reliable_reader>
</protocol>
</datareader_qos>
</qos_profile>

<!-- This is the profile used by the Requester.
It inherits from "default", defined above,
and overrides some QoS -->
<qos_profile name="RequesterExampleProfile" base_name="default">

<!-- QoS for the data writer that sends requests -->
<datawriter_qos>
<durability>
<kind>TRANSIENT_LOCAL_DURABILITY_QOS</kind>
</durability>
</datawriter_qos>

<!-- QoS for the data reader that receives replies -->
<datareader_qos>
<durability>
<kind>VOLATILE_DURABILITY_QOS</kind>
</durability>
</datareader_qos>
</qos_profile>

<!-- This is the profile used by the Replier.
It inherits from "default", defined above,
and overrides some QoS -->
<qos_profile name="ReplierExampleProfile" base_name="default">

<!-- QoS for the data writer that sends replies -->
<datawriter_qos>
<durability>
<kind>VOLATILE_DURABILITY_QOS</kind>
</durability>
</datawriter_qos>

<!-- QoS for the data reader that receives requests -->
<datareader_qos>
<durability>
<kind>TRANSIENT_LOCAL_DURABILITY_QOS</kind>
</durability>
</datareader_qos>
</qos_profile>

</qos_library>
</dds>
Loading