pub struct EmbeddedServiceClient<Svc, const REQ_BUF: usize = nros_node::::executor::handles::EmbeddedServiceClient::{constant#0}, const REPLY_BUF: usize = nros_node::::executor::handles::EmbeddedServiceClient::{constant#1}>where
Svc: RosService,{ /* private fields */ }Expand description
Typed service client handle with internal buffers.
Implementations§
Source§impl<Svc, const REQ_BUF: usize, const REPLY_BUF: usize> EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>where
Svc: RosService,
impl<Svc, const REQ_BUF: usize, const REPLY_BUF: usize> EmbeddedServiceClient<Svc, REQ_BUF, REPLY_BUF>where
Svc: RosService,
Sourcepub fn call(
&mut self,
request: &<Svc as RosService>::Request,
) -> Result<Promise<'_, <Svc as RosService>::Reply>, NodeError>
pub fn call( &mut self, request: &<Svc as RosService>::Request, ) -> Result<Promise<'_, <Svc as RosService>::Reply>, NodeError>
Call the service (non-blocking). Returns a Promise that can be polled.
Use with Executor::spin_once() to drive I/O while waiting:
let mut promise = client.call(&request)?;
loop {
executor.spin_once(core::time::Duration::from_millis(10));
if let Some(reply) = promise.try_recv()? {
break;
}
}§Errors
Returns NodeError::RequestInFlight if a previous call’s reply
has not been received. This prevents the old hazard where dropping
a Promise without awaiting its reply left the stale reply
queued to land on the next call. Resolve by
polling the existing promise to completion or calling
reset_in_flight.
Sourcepub fn reset_in_flight(&mut self)
pub fn reset_in_flight(&mut self)
Explicitly clear the in-flight flag (Phase 84.D3).
Call this if a previous Promise was dropped without completing
and you want to abandon the pending reply. The next
call will proceed but may still observe the stale
reply if one is in the transport’s queue — callers that need strict
correctness should drain / ignore one extra try_recv first.
Sourcepub fn wait_for_service(
&mut self,
executor: &mut Executor,
timeout: Duration,
) -> Result<bool, NodeError>
pub fn wait_for_service( &mut self, executor: &mut Executor, timeout: Duration, ) -> Result<bool, NodeError>
Block until at least one matching service server is discoverable on
the network, or timeout elapses.
Returns Ok(true) if a matching server reported back inside the
budget; Ok(false) on timeout (no server visible). Mirrors
rclcpp::ClientBase::wait_for_service and
rclpy.client.Client.wait_for_service.
On the Zenoh backend this issues a z_liveliness_get against the
matching server’s wildcarded liveliness keyexpr; the executor is
spun cooperatively while the query is in flight so other
subscribers / timers continue to make progress. Backends without
liveliness discovery answer Ok(true) immediately (default trait
impl in nros-rmw), so the call is a no-op cost when discovery
isn’t supported.
Recommended usage — gate the first call() on this:
let mut client = node.create_client::<AddTwoInts>("/add_two_ints")?;
if !client.wait_for_service(&mut executor, Duration::from_secs(5))? {
return Err(NodeError::Timeout);
}
let mut promise = client.call(&request)?;Once the server is observed, the result is latched: subsequent
service_is_ready checks return true without another round
trip. This matches rclcpp’s snapshot semantic — discovery isn’t
re-proven on every call.
Sourcepub fn service_is_ready(&self) -> bool
pub fn service_is_ready(&self) -> bool
Snapshot whether a matching service server is currently visible.
Non-blocking. Matches rclcpp::ClientBase::service_is_ready and
rclpy.client.Client.service_is_ready. Backends without liveliness
discovery return true (assume always reachable).
Sourcepub fn server_available(&self) -> Result<bool, NodeError>
pub fn server_available(&self) -> Result<bool, NodeError>
Phase 124.C.3 — graph-aware server-availability probe.
Returns Ok(true) / Ok(false) when the backend can answer
(zenoh queryable interest, DDS built-in topic reader), or
Err(NodeError::Transport(Unsupported)) when it can’t (XRCE
agent without participant enumeration). Distinct from
service_is_ready — that one
collapses “no” and “don’t know” into the same false.
Used to gate the first call_raw so a startup-ordering race
(client opens before server’s discovery announcement lands)
doesn’t surface as a request-side timeout.