Skip to content

Commit 8939292

Browse files
committed
Refs #23079. Add calculator IDL and example python code.
Signed-off-by: Miguel Company <miguelcompany@eprosima.com>
1 parent a8288c6 commit 8939292

2 files changed

Lines changed: 328 additions & 0 deletions

File tree

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
#!/usr/bin/env python3
2+
# # Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
"""
16+
Script to test Fast DDS python bindings for RPC
17+
"""
18+
import os
19+
import argparse
20+
import time
21+
22+
import fastdds
23+
import calculator
24+
25+
DESCRIPTION = """Calculator RPC example for Fast DDS python bindings"""
26+
USAGE = ('python3 CalculatorExample.py -p client|server [-d domainID -t server_threads]')
27+
28+
### Server implementation ###
29+
30+
class MyCalculatorImplementation(calculator.CalculatorServerImplementation):
31+
def __init__(self):
32+
super().__init__()
33+
34+
def operation_call_print(self, info, operation_name):
35+
print("Operation {op} called from client with id {id}".format(op=operation_name, id=info.get_client_id()))
36+
37+
def addition(self, info, value1, value2):
38+
self.operation_call_print(info, "addition")
39+
return value1 + value2
40+
41+
def subtraction(self, info, value1, value2):
42+
self.operation_call_print(info, "subtraction")
43+
return value1 - value2
44+
45+
def representation_limits(self, info):
46+
self.operation_call_print(info, "representation_limits")
47+
return -2147483648, 2147483647
48+
49+
def fibonacci_seq(self, info, n_results, result_writer):
50+
self.operation_call_print(info, "fibonacci_seq")
51+
a = 1
52+
b = 1
53+
c = 0
54+
55+
while n_results > 0:
56+
n_results = n_results - 1
57+
58+
result_writer.write(a)
59+
c = a + b
60+
a = b
61+
b = c
62+
63+
def sum_all(self, info, value):
64+
self.operation_call_print(info, "sum_all")
65+
ret = 0
66+
has_value, n = value.read()
67+
while has_value:
68+
ret = ret + n
69+
has_value, n = value.read()
70+
return ret
71+
72+
def accumulator(self, info, value, result_writer):
73+
self.operation_call_print(info, "accumulator")
74+
ret = 0
75+
has_value, n = value.read()
76+
while has_value:
77+
ret = ret + n
78+
result_writer.write(ret)
79+
has_value, n = value.read()
80+
81+
### Server application ###
82+
83+
class Server:
84+
def __init__(self, domain, num_threads):
85+
# Create participant
86+
factory = fastdds.DomainParticipantFactory.get_instance()
87+
self.participant_qos = fastdds.DomainParticipantQos()
88+
factory.get_default_participant_qos(self.participant_qos)
89+
self.participant = factory.create_participant(domain, self.participant_qos)
90+
91+
# Create server
92+
self.implementation = MyCalculatorImplementation()
93+
self.server_qos = fastdds.ReplierQos()
94+
self.server = calculator.create_CalculatorServer(
95+
self.participant, "my_calculator", self.server_qos, num_threads, self.implementation)
96+
97+
def run(self):
98+
print("Starting server. Process will block forever.")
99+
self.server.run()
100+
101+
### Client application ###
102+
103+
class Client:
104+
def __init__(self, domain):
105+
# Create participant
106+
factory = fastdds.DomainParticipantFactory.get_instance()
107+
self.participant_qos = fastdds.DomainParticipantQos()
108+
factory.get_default_participant_qos(self.participant_qos)
109+
self.participant = factory.create_participant(domain, self.participant_qos)
110+
111+
# Create client
112+
self.client_qos = fastdds.RequesterQos()
113+
self.client = calculator.create_CalculatorClient(
114+
self.participant, "my_calculator", self.client_qos)
115+
116+
def run(self):
117+
# TODO: wait for server to be ready
118+
time.sleep(2)
119+
120+
self.perform_addition()
121+
self.perform_subtraction()
122+
self.perform_representation_limits()
123+
self.perform_fibonacci_seq()
124+
self.perform_sum_all()
125+
self.perform_accumulator()
126+
127+
def perform_addition(self):
128+
try:
129+
# Perform basic addition
130+
print("Performing addition(1, 2)")
131+
result = self.client.addition(1, 2)
132+
print("Result: {}".format(result.get()))
133+
134+
# Perform addition with overflow
135+
print("Performing addition(2147483647, 1)")
136+
result = self.client.addition(2147483647, 1)
137+
print("Result: {}".format(result=result.get()))
138+
except Exception as e:
139+
print("Exception: {}".format(type(e).__name__))
140+
print("Exception message: {}".format(e))
141+
142+
def perform_subtraction(self):
143+
try:
144+
# Perform basic subtraction
145+
print("Performing subtraction(2, 1)")
146+
result = self.client.subtraction(2, 1)
147+
print("Result: {}".format(result.get()))
148+
149+
# Perform subtraction with underflow
150+
print("Performing subtraction(-2147483648, 1)")
151+
result = self.client.subtraction(-2147483648, 1)
152+
result.wait()
153+
print("Result: {}".format(result=result.get()))
154+
except Exception as e:
155+
print("Exception: {}".format(type(e).__name__))
156+
print("Exception message: {}".format(e))
157+
158+
def perform_representation_limits(self):
159+
try:
160+
# Perform representation limits
161+
self.min = 0
162+
self.max = 0
163+
print("Performing representation_limits()")
164+
result = self.client.representation_limits(self.min, self.max)
165+
result.get()
166+
print("Result: {min}, {max}".format(min=self.min, max=self.max))
167+
except Exception as e:
168+
print("Exception: {}".format(type(e).__name__))
169+
print("Exception message: {}".format(e))
170+
171+
def perform_fibonacci_seq(self):
172+
try:
173+
print("Performing fibonacci_seq(10)")
174+
result = self.client.fibonacci_seq(10)
175+
has_value, n = result.read()
176+
while has_value:
177+
print("Result: {}".format(n))
178+
has_value, n = result.read()
179+
except Exception as e:
180+
print("Exception: {}".format(type(e).__name__))
181+
print("Exception message: {}".format(e))
182+
183+
def perform_sum_all(self):
184+
try:
185+
print("Performing sum_all([1, 2, 3, 4, 5])")
186+
result, value = self.client.sum_all()
187+
value.write(1)
188+
value.write(2)
189+
value.write(3)
190+
value.write(4)
191+
value.write(5)
192+
value.finish()
193+
print("Result: {}".format(result.get()))
194+
except Exception as e:
195+
print("Exception: {}".format(type(e).__name__))
196+
print("Exception message: {}".format(e))
197+
198+
def perform_accumulator(self):
199+
try:
200+
print("Performing accumulator([1, 2, 3, 4, 5])")
201+
result, value = self.client.accumulator()
202+
value.write(1)
203+
value.write(2)
204+
value.write(3)
205+
value.write(4)
206+
value.write(5)
207+
value.finish()
208+
has_value, n = result.read()
209+
while has_value:
210+
print("Result: {}".format(n))
211+
has_value, n = result.read()
212+
except Exception as e:
213+
print("Exception: {}".format(type(e).__name__))
214+
print("Exception message: {}".format(e))
215+
216+
def parse_options():
217+
""""
218+
Parse arguments.
219+
220+
:return: Parsed arguments.
221+
"""
222+
parser = argparse.ArgumentParser(
223+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
224+
add_help=True,
225+
description=(DESCRIPTION),
226+
usage=(USAGE)
227+
)
228+
required_args = parser.add_argument_group('required arguments')
229+
required_args.add_argument(
230+
'-d',
231+
'--domain',
232+
type=int,
233+
required=False,
234+
help='DomainID.'
235+
)
236+
required_args.add_argument(
237+
'-p',
238+
'--parameter',
239+
type=str,
240+
required=True,
241+
help='Whether the application is run as client or server.'
242+
)
243+
required_args.add_argument(
244+
'-t',
245+
'--server_threads',
246+
type=int,
247+
required=False,
248+
help='Number of threads in the server pool. Only applies if the application is run as server.'
249+
)
250+
return parser.parse_args()
251+
252+
if __name__ == '__main__':
253+
# Parse arguments
254+
args = parse_options()
255+
if not args.domain:
256+
args.domain = 0
257+
if not args.server_threads:
258+
args.server_threads = 1
259+
260+
if args.parameter == 'client':
261+
print('Creating client.')
262+
client = Client(args.domain)
263+
client.run()
264+
elif args.parameter == 'server':
265+
print('Creating server.')
266+
server = Server(args.domain, args.server_threads)
267+
server.run()
268+
else:
269+
print('Error: Incorrect arguments.')
270+
print(USAGE)
271+
272+
exit()
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2025 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
module calculator_base
16+
{
17+
// This exception will be thrown when an operation result cannot be represented in a long
18+
exception OverflowException
19+
{
20+
};
21+
22+
@nested
23+
interface Adder
24+
{
25+
// Returns the result of value1 + value2
26+
long addition(in long value1, in long value2) raises(OverflowException);
27+
};
28+
29+
@nested
30+
interface Subtractor
31+
{
32+
// Returns the result of value1 - value2
33+
long subtraction(in long value1, in long value2) raises(OverflowException);
34+
};
35+
36+
interface BasicCalculator : Adder, Subtractor
37+
{
38+
// Returns the minimum and maximum representable values
39+
void representation_limits(out long min_value, out long max_value);
40+
};
41+
};
42+
43+
interface Calculator : calculator_base::BasicCalculator
44+
{
45+
// Returns a feed of results with the n_results first elements of the Fibonacci sequence
46+
// E.g. for an input of 5, returns a feed with {1, 1, 2, 3, 5}
47+
@feed long fibonacci_seq(in unsigned long n_results) raises (calculator_base::OverflowException);
48+
49+
// Waits for an input feed to finish and returns the sum of all the received values
50+
// E.g. for an input of {1, 2, 3, 4, 5} returns 15
51+
long sum_all(@feed in long value) raises (calculator_base::OverflowException);
52+
53+
// Returns a feed of results with the sum of all received values
54+
// E.g. for an input of {1, 2, 3, 4, 5}, returns a feed with {1, 3, 6, 10, 15}
55+
@feed long accumulator(@feed in long value) raises (calculator_base::OverflowException);
56+
};

0 commit comments

Comments
 (0)