Struct HostClient

Source
pub struct HostClient<WireErr> { /* private fields */ }
Expand description

The HostClient is the primary PC-side interface.

It is generic over a single type, WireErr, which can be used by the embedded system when a request was not understood, or some other error has occurred.

HostClients can be cloned, and used across multiple tasks/threads.

There are currently two ways to create one, based on the transport used:

  1. With raw USB Bulk transfers: HostClient::new_raw_nusb() (recommended)
  2. With cobs CDC-ACM transfers: HostClient::new_serial_cobs()

Implementations§

Source§

impl<WireErr> HostClient<WireErr>
where WireErr: DeserializeOwned + Schema,

§nusb Constructor Methods

These methods are used to create a new HostClient instance for use with nusb and USB bulk transfer encoding.

Requires feature: raw-nusb

Source

pub fn try_new_raw_nusb<F: FnMut(&DeviceInfo) -> bool>( func: F, err_uri_path: &str, outgoing_depth: usize, seq_no_kind: VarSeqKind, ) -> Result<Self, String>

Try to create a new link using nusb for connectivity

The provided function will be used to find a matching device. The first matching device will be connected to. err_uri_path is the path associated with the WireErr message type.

Returns an error if no device could be found, or if there was an error connecting to the device.

This constructor is available when the raw-nusb feature is enabled.

§Platform specific support

When using Windows, the WinUSB driver does not allow enumerating interfaces. When on windows, this method will ALWAYS try to connect to interface zero. This limitation may be removed in the future, and if so, will be changed to look for the first interface with the class of 0xFF.

§Example
use postcard_rpc::host_client::HostClient;
use postcard_rpc::header::VarSeqKind;
use serde::{Serialize, Deserialize};
use postcard_schema::Schema;

/// A "wire error" type your server can use to respond to any
/// kind of request, for example if deserializing a request fails
#[derive(Debug, PartialEq, Schema, Serialize, Deserialize)]
pub enum Error {
   SomethingBad
}

let client = HostClient::<Error>::try_new_raw_nusb(
    // Find the first device with the serial 12345678
    |d| d.serial_number() == Some("12345678"),
    // the URI/path for `Error` messages
    "error",
    // Outgoing queue depth in messages
    8,
    // Use one-byte sequence numbers
    VarSeqKind::Seq1,
).unwrap();
Source

pub fn try_new_raw_nusb_with_interface<F1: FnMut(&DeviceInfo) -> bool, F2: FnMut(&InterfaceInfo) -> bool>( device_func: F1, interface_func: F2, err_uri_path: &str, outgoing_depth: usize, seq_no_kind: VarSeqKind, ) -> Result<Self, String>

Try to create a new link using nusb for connectivity

The provided function will be used to find a matching device. The first matching device will be connected to. err_uri_path is the path associated with the WireErr message type.

Returns an error if no device or interface could be found, or if there was an error connecting to the device or interface.

This constructor is available when the raw-nusb feature is enabled.

§Platform specific support

When using Windows, the WinUSB driver does not allow enumerating interfaces. Therefore, this constructor is not available on windows. This limitation may be removed in the future.

§Example
use postcard_rpc::host_client::HostClient;
use postcard_rpc::header::VarSeqKind;
use serde::{Serialize, Deserialize};
use postcard_schema::Schema;

/// A "wire error" type your server can use to respond to any
/// kind of request, for example if deserializing a request fails
#[derive(Debug, PartialEq, Schema, Serialize, Deserialize)]
pub enum Error {
   SomethingBad
}

let client = HostClient::<Error>::try_new_raw_nusb_with_interface(
    // Find the first device with the serial 12345678
    |d| d.serial_number() == Some("12345678"),
    // Find the "Vendor Specific" interface
    |i| i.class() == 0xFF,
    // the URI/path for `Error` messages
    "error",
    // Outgoing queue depth in messages
    8,
    // Use one-byte sequence numbers
    VarSeqKind::Seq1,
).unwrap();
Source

pub fn new_raw_nusb<F: FnMut(&DeviceInfo) -> bool>( func: F, err_uri_path: &str, outgoing_depth: usize, seq_no_kind: VarSeqKind, ) -> Self

Create a new link using nusb for connectivity

Panics if connection fails. See Self::try_new_raw_nusb() for more details.

This constructor is available when the raw-nusb feature is enabled.

§Example
use postcard_rpc::host_client::HostClient;
use postcard_rpc::header::VarSeqKind;
use serde::{Serialize, Deserialize};
use postcard_schema::Schema;

/// A "wire error" type your server can use to respond to any
/// kind of request, for example if deserializing a request fails
#[derive(Debug, PartialEq, Schema, Serialize, Deserialize)]
pub enum Error {
   SomethingBad
}

let client = HostClient::<Error>::new_raw_nusb(
    // Find the first device with the serial 12345678
    |d| d.serial_number() == Some("12345678"),
    // the URI/path for `Error` messages
    "error",
    // Outgoing queue depth in messages
    8,
    // Use one-byte sequence numbers
    VarSeqKind::Seq1,
);
Source§

impl<WireErr> HostClient<WireErr>
where WireErr: DeserializeOwned + Schema,

§Serial Constructor Methods

These methods are used to create a new HostClient instance for use with tokio serial and cobs encoding.

Requires feature: cobs-serial

Source

pub fn try_new_serial_cobs( serial_path: &str, err_uri_path: &str, outgoing_depth: usize, baud: u32, seq_no_kind: VarSeqKind, ) -> Result<Self, String>

Create a new HostClient

serial_path is the path to the serial port used. err_uri_path is the path associated with the WireErr message type.

This constructor is available when the cobs-serial feature is enabled.

§Example
use postcard_rpc::host_client::HostClient;
use postcard_rpc::header::VarSeqKind;
use serde::{Serialize, Deserialize};
use postcard_schema::Schema;

/// A "wire error" type your server can use to respond to any
/// kind of request, for example if deserializing a request fails
#[derive(Debug, PartialEq, Schema, Serialize, Deserialize)]
pub enum Error {
   SomethingBad
}

let client = HostClient::<Error>::new_serial_cobs(
    // the serial port path
    "/dev/ttyACM0",
    // the URI/path for `Error` messages
    "error",
    // Outgoing queue depth in messages
    8,
    // Baud rate of serial (does not generally matter for
    //  USB UART/CDC-ACM serial connections)
    115_200,
    // Use one-byte sequence numbers
    VarSeqKind::Seq1,
);
Source

pub fn new_serial_cobs( serial_path: &str, err_uri_path: &str, outgoing_depth: usize, baud: u32, seq_no_kind: VarSeqKind, ) -> Self

Create a new HostClient

Panics if we couldn’t open the serial port.

See HostClient::try_new_serial_cobs for more details

Source§

impl<WireErr> HostClient<WireErr>
where WireErr: DeserializeOwned + Schema,

Source

pub fn new_with_wire<WTX, WRX, WSP>( tx: WTX, rx: WRX, sp: WSP, seq_kind: VarSeqKind, err_uri_path: &str, outgoing_depth: usize, ) -> Self
where WTX: WireTx, WRX: WireRx, WSP: WireSpawn,

Generic HostClient logic, using the various Wire traits

Typically used internally, but may also be used to implement HostClient over arbitrary transports.

Source

pub fn new_with_wire_and_config<WTX, WRX, WSP>( tx: WTX, rx: WRX, sp: WSP, config: &HostClientConfig<'_>, ) -> Self
where WTX: WireTx, WRX: WireRx, WSP: WireSpawn,

Generic HostClient logic, using the various Wire traits

Typically used internally, but may also be used to implement HostClient over arbitrary transports.

Source§

impl<WireErr> HostClient<WireErr>
where WireErr: DeserializeOwned + Schema,

§Interface Methods

Source

pub async fn get_schema_report( &self, ) -> Result<SchemaReport, SchemaError<WireErr>>

Obtain a SchemaReport describing the connected device

Source

pub async fn send_resp<E: Endpoint>( &self, t: &E::Request, ) -> Result<E::Response, HostErr<WireErr>>

Send a message of type Endpoint::Request to path, and await a response of type Endpoint::Response (or WireErr) to path.

This function will wait potentially forever. Consider using with a timeout.

Source

pub async fn send_resp_raw( &self, rqst: RpcFrame, resp_key: Key, ) -> Result<RpcFrame, HostErr<WireErr>>

Perform an endpoint request/response,but without handling the Ser/De automatically

Source

pub async fn publish<T: Topic>( &self, seq_no: VarSeq, msg: &T::Message, ) -> Result<(), IoClosed>
where T::Message: Serialize,

Publish a Topic Message.

There is no feedback if the server received our message. If the I/O worker is closed, an error is returned.

Source

pub async fn publish_raw(&self, frame: RpcFrame) -> Result<(), IoClosed>

Publish the given raw frame

Source

pub async fn subscribe_multi<T: Topic>( &self, depth: usize, ) -> Result<MultiSubscription<T::Message>, IoClosed>

Begin listening to a Topic, receiving a Subscription that will give a stream of Messages. Unlike subscribe, multiple subscribers to the same stream are allowed, and behave as a broadcast channel.

Returns an Error if the I/O worker is closed.

Source

pub async fn subscribe_multi_raw( &self, key: Key, depth: usize, ) -> Result<RawMultiSubscription, IoClosed>

Subscribe to the given Key, without automatically handling deserialization

Source

pub async fn subscribe<T: Topic>( &self, depth: usize, ) -> Result<Subscription<T::Message>, IoClosed>

👎Deprecated: In future versions, subscribe will be removed. Use subscribe_multi or subscribe_exclusive instead.

Begin listening to a Topic, receiving a Subscription that will give a stream of Messages.

If you subscribe to the same topic multiple times, the previous subscription will be closed (there can be only one). This does not apply to subscriptions created with subscribe_multi. This also WILL close subscriptions opened by subscribe_exclusive.

Returns an Error if the I/O worker is closed.

Source

pub async fn subscribe_raw( &self, key: Key, depth: usize, ) -> Result<RawSubscription, IoClosed>

👎Deprecated: In future versions, subscribe_raw will be removed. Use subscribe_multi_raw or subscribe_exclusive_raw instead.

Subscribe to the given Key, without automatically handling deserialization.

If you subscribe to the same topic multiple times, the previous subscription will be closed (there can be only one). This does not apply to subscriptions created with subscribe_multi.

Returns an Error if the I/O worker is closed.

Source

pub async fn subscribe_exclusive<T: Topic>( &self, depth: usize, ) -> Result<Subscription<T::Message>, SubscribeError>

Begin listening to a Topic, receiving a Subscription that will give a stream of Messages.

If you try to subscribe to the same topic multiple times, this function returns a SubscribeError::AlreadySubscribed (there can be only one). This does not apply to subscriptions created with subscribe_multi.

Returns an Error if the I/O worker is closed.

Source

pub async fn subscribe_exclusive_raw( &self, key: Key, depth: usize, ) -> Result<RawSubscription, SubscribeError>

Subscribe to the given Key, without automatically handling deserialization.

If you try to subscribe to the same topic multiple times, this function returns a SubscribeError::AlreadySubscribed (there can be only one). This does not apply to subscriptions created with subscribe_multi.

Returns an Error if the I/O worker is closed.

Source

pub fn close(&self)

Permanently close the connection to the client

All other HostClients sharing the connection (e.g. created by cloning a single HostClient) will also stop, and no further communication will succeed. The in-flight messages will not be flushed.

This will also signal any I/O worker tasks to halt immediately as well.

Source

pub fn is_closed(&self) -> bool

Has this host client been closed?

Source

pub async fn wait_closed(&self)

Wait for the host client to be closed

Trait Implementations§

Source§

impl<WireErr> Clone for HostClient<WireErr>

Source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<WireErr> Freeze for HostClient<WireErr>

§

impl<WireErr> !RefUnwindSafe for HostClient<WireErr>

§

impl<WireErr> Send for HostClient<WireErr>

§

impl<WireErr> Sync for HostClient<WireErr>

§

impl<WireErr> Unpin for HostClient<WireErr>

§

impl<WireErr> !UnwindSafe for HostClient<WireErr>

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dst: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more