Skip to main content

CommandClient

Struct CommandClient 

Source
pub struct CommandClient { /* private fields */ }
Expand description

A non-blocking client for sending IPC commands to external modules.

CommandClient is constructed by ControlRunner during startup and passed to the control program each cycle via TickContext::client.

All methods are non-blocking and safe to call from process_tick.

Multiple subsystems (state machines, modules) can share a single CommandClient. Each subsystem calls send() to issue requests and take_response() to claim its own responses by transaction_id. The framework calls poll() once per tick before process_tick, so incoming messages are already buffered.

Implementations§

Source§

impl CommandClient

Source

pub fn new( write_tx: UnboundedSender<String>, response_rx: UnboundedReceiver<CommandMessage>, ) -> Self

Create a new CommandClient from channels created by ControlRunner.

Source

pub fn send(&mut self, topic: &str, data: Value) -> u32

Send a command request to an external module.

Creates a CommandMessage::request with the given topic and data, serializes it, and pushes it into the WebSocket write channel.

Returns the transaction_id which can be used to match the response.

§Arguments
  • topic - Fully-qualified topic name (e.g., "labelit.translate_check")
  • data - JSON payload for the request
Source

pub fn poll(&mut self)

Drain all available responses from the WebSocket channel into the internal buffer.

Call this once per tick at the top of process_tick, before any subsystem calls take_response(). This ensures every subsystem sees responses that arrived since the last cycle.

Source

pub fn take_response(&mut self, transaction_id: u32) -> Option<CommandMessage>

Take a response for a specific transaction_id from the buffer.

Returns Some(response) if a response with that ID has been received, or None if it hasn’t arrived yet. The response is removed from the buffer on retrieval.

This is the recommended way for subsystems to retrieve their responses, since each subsystem only claims its own transaction_id and cannot accidentally consume another subsystem’s response.

§Example
// In a subsystem's tick method:
if let Some(response) = client.take_response(self.my_tid) {
    if response.success {
        // handle success
    } else {
        // handle error
    }
}
Source

pub fn is_pending(&self, transaction_id: u32) -> bool

Check if a request is still awaiting a response.

Returns true if the request has been sent but no response has arrived yet. Returns false if the response is already buffered (even if not yet claimed via take_response()) or if the transaction ID is unknown.

Source

pub fn pending_count(&self) -> usize

Number of outstanding requests (sent but no response received yet).

Source

pub fn response_count(&self) -> usize

Number of responses buffered and ready to be claimed.

Source

pub fn drain_stale(&mut self, timeout: Duration) -> Vec<u32>

Remove and return transaction IDs that have been pending longer than timeout.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V