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:
- With raw USB Bulk transfers:
HostClient::new_raw_nusb()
(recommended) - 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.
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
Sourcepub 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>
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();
Sourcepub 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>
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();
Sourcepub fn new_raw_nusb<F: FnMut(&DeviceInfo) -> bool>(
func: F,
err_uri_path: &str,
outgoing_depth: usize,
seq_no_kind: VarSeqKind,
) -> Self
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.
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
Sourcepub fn try_new_serial_cobs(
serial_path: &str,
err_uri_path: &str,
outgoing_depth: usize,
baud: u32,
seq_no_kind: VarSeqKind,
) -> Result<Self, String>
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,
);
Sourcepub fn new_serial_cobs(
serial_path: &str,
err_uri_path: &str,
outgoing_depth: usize,
baud: u32,
seq_no_kind: VarSeqKind,
) -> Self
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,
impl<WireErr> HostClient<WireErr>where
WireErr: DeserializeOwned + Schema,
Sourcepub fn new_with_wire<WTX, WRX, WSP>(
tx: WTX,
rx: WRX,
sp: WSP,
seq_kind: VarSeqKind,
err_uri_path: &str,
outgoing_depth: usize,
) -> Self
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
Generic HostClient logic, using the various Wire traits
Typically used internally, but may also be used to implement HostClient over arbitrary transports.
Sourcepub fn new_with_wire_and_config<WTX, WRX, WSP>(
tx: WTX,
rx: WRX,
sp: WSP,
config: &HostClientConfig<'_>,
) -> Self
pub fn new_with_wire_and_config<WTX, WRX, WSP>( tx: WTX, rx: WRX, sp: WSP, config: &HostClientConfig<'_>, ) -> Self
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
impl<WireErr> HostClient<WireErr>where
WireErr: DeserializeOwned + Schema,
§Interface Methods
Sourcepub async fn get_schema_report(
&self,
) -> Result<SchemaReport, SchemaError<WireErr>>
pub async fn get_schema_report( &self, ) -> Result<SchemaReport, SchemaError<WireErr>>
Obtain a SchemaReport
describing the connected device
Sourcepub async fn send_resp<E: Endpoint>(
&self,
t: &E::Request,
) -> Result<E::Response, HostErr<WireErr>>
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.
Sourcepub async fn send_resp_raw(
&self,
rqst: RpcFrame,
resp_key: Key,
) -> Result<RpcFrame, HostErr<WireErr>>
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
Sourcepub async fn publish<T: Topic>(
&self,
seq_no: VarSeq,
msg: &T::Message,
) -> Result<(), IoClosed>
pub async fn publish<T: Topic>( &self, seq_no: VarSeq, msg: &T::Message, ) -> Result<(), IoClosed>
Sourcepub async fn publish_raw(&self, frame: RpcFrame) -> Result<(), IoClosed>
pub async fn publish_raw(&self, frame: RpcFrame) -> Result<(), IoClosed>
Publish the given raw frame
Sourcepub async fn subscribe_multi<T: Topic>(
&self,
depth: usize,
) -> Result<MultiSubscription<T::Message>, IoClosed>where
T::Message: DeserializeOwned,
pub async fn subscribe_multi<T: Topic>(
&self,
depth: usize,
) -> Result<MultiSubscription<T::Message>, IoClosed>where
T::Message: DeserializeOwned,
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.
Sourcepub async fn subscribe_multi_raw(
&self,
key: Key,
depth: usize,
) -> Result<RawMultiSubscription, IoClosed>
pub async fn subscribe_multi_raw( &self, key: Key, depth: usize, ) -> Result<RawMultiSubscription, IoClosed>
Subscribe to the given Key
, without automatically handling deserialization
Sourcepub async fn subscribe<T: Topic>(
&self,
depth: usize,
) -> Result<Subscription<T::Message>, IoClosed>where
T::Message: DeserializeOwned,
👎Deprecated: In future versions, subscribe
will be removed. Use subscribe_multi
or subscribe_exclusive
instead.
pub async fn subscribe<T: Topic>(
&self,
depth: usize,
) -> Result<Subscription<T::Message>, IoClosed>where
T::Message: DeserializeOwned,
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.
Sourcepub 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.
pub async fn subscribe_raw( &self, key: Key, depth: usize, ) -> Result<RawSubscription, IoClosed>
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.
Sourcepub async fn subscribe_exclusive<T: Topic>(
&self,
depth: usize,
) -> Result<Subscription<T::Message>, SubscribeError>where
T::Message: DeserializeOwned,
pub async fn subscribe_exclusive<T: Topic>(
&self,
depth: usize,
) -> Result<Subscription<T::Message>, SubscribeError>where
T::Message: DeserializeOwned,
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.
Sourcepub async fn subscribe_exclusive_raw(
&self,
key: Key,
depth: usize,
) -> Result<RawSubscription, SubscribeError>
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.
Sourcepub fn close(&self)
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.
Sourcepub async fn wait_closed(&self)
pub async fn wait_closed(&self)
Wait for the host client to be closed