use std::time::Duration;
use clap::Parser;
use hiroz::{Builder, context::ZContextBuilder};
use hiroz_msgs::example_interfaces::{AddTwoIntsRequest, AddTwoIntsResponse, srv::AddTwoInts};
#[derive(Debug, Parser)]
#[command(
name = "z_srvcli_ros2dds",
about = "ROS 2 service demo using ros2dds backend"
)]
struct Args {
#[arg(short, long, default_value = "server")]
role: String,
#[arg(short, long, default_value = "5")]
a: i64,
#[arg(short, long, default_value = "3")]
b: i64,
#[arg(short, long, default_value = "add_two_ints")]
service: String,
#[arg(short, long, default_value = "tcp/127.0.0.1:7447")]
endpoint: String,
#[arg(short, long, default_value = "1")]
count: usize,
}
#[tokio::main]
async fn main() -> hiroz::Result<()> {
zenoh::init_log_from_env_or("info");
let args = Args::parse();
println!("=== ros2dds Backend Service Demo ===");
println!("Backend: ros2dds");
println!("Service: {}", args.service);
println!("Role: {}", args.role);
println!();
let ctx = ZContextBuilder::default()
.with_connect_endpoints([args.endpoint.as_str()])
.keyexpr_format(hiroz_protocol::KeyExprFormat::Ros2Dds)
.build()?;
match args.role.as_str() {
"server" => run_server(ctx, &args).await,
"client" => run_client(ctx, &args).await,
_ => {
println!("Unknown role: {}. Use 'server' or 'client'.", args.role);
Ok(())
}
}
}
async fn run_server(ctx: hiroz::context::ZContext, args: &Args) -> hiroz::Result<()> {
println!("Starting AddTwoInts service server with ros2dds backend...\n");
let node = ctx.create_node("add_two_ints_server").build()?;
let mut service = node.create_service::<AddTwoInts>(&args.service).build()?;
println!("Service server ready, waiting for requests...\n");
let max_requests = if args.count == 0 {
None
} else {
Some(args.count)
};
let mut request_count = 0;
loop {
let req = service.take_request()?;
println!("Incoming request:");
println!(" a: {}", req.message().a);
println!(" b: {}", req.message().b);
let sum = req.message().a + req.message().b;
let resp = AddTwoIntsResponse { sum };
println!("Sending response: {}\n", resp.sum);
req.reply_blocking(&resp)?;
request_count += 1;
if let Some(max) = max_requests
&& request_count >= max
{
println!("Handled {} requests, exiting.", request_count);
break;
}
}
Ok(())
}
async fn run_client(ctx: hiroz::context::ZContext, args: &Args) -> hiroz::Result<()> {
println!("Starting AddTwoInts service client with ros2dds backend...\n");
let node = ctx.create_node("add_two_ints_client").build()?;
let client = node.create_client::<AddTwoInts>(&args.service).build()?;
println!("Service client ready\n");
let max_requests = if args.count == 0 {
usize::MAX
} else {
args.count
};
for i in 0..max_requests {
let req = AddTwoIntsRequest {
a: args.a + i as i64,
b: args.b,
};
println!("Sending request #{}: a={}, b={}", i + 1, req.a, req.b);
match client.call_with_timeout(&req, Duration::from_secs(5)).await {
Ok(resp) => {
println!("Received response: {} + {} = {}\n", req.a, req.b, resp.sum);
}
Err(e) => {
println!("Failed to receive response: {}\n", e);
}
}
if i + 1 < max_requests {
tokio::time::sleep(Duration::from_millis(500)).await;
}
}
println!("Client finished sending {} requests.", max_requests);
Ok(())
}