Skip to main content

ImClient

Trait ImClient 

Source
pub trait ImClient<'a>: Sized + Into<Exchange<'a>> {
    // Provided methods
    async fn read_with<B>(self, build: B) -> Result<ReadRespChunk<'a>, Error>
       where B: FnMut(ReadReqBuilder<ReadSender<'a>>) -> Result<ReadSender<'a>, Error> { ... }
    async fn read_sender(self) -> Result<ReadSender<'a>, Error> { ... }
    async fn write_with<B>(
        self,
        timed_timeout_ms: Option<u16>,
        build: B,
    ) -> Result<WriteRespHandle<'a>, Error>
       where B: FnMut(WriteReqBuilder<WriteSender<'a>>) -> Result<WriteSender<'a>, Error> { ... }
    async fn write_sender(
        self,
        timed_timeout_ms: Option<u16>,
    ) -> Result<WriteSender<'a>, Error> { ... }
    async fn invoke_with<B>(
        self,
        timed_timeout_ms: Option<u16>,
        build: B,
    ) -> Result<InvokeRespChunk<'a>, Error>
       where B: FnMut(InvReqBuilder<InvokeSender<'a>>) -> Result<InvokeSender<'a>, Error> { ... }
    async fn invoke_sender(
        self,
        timed_timeout_ms: Option<u16>,
    ) -> Result<InvokeSender<'a>, Error> { ... }
    async fn subscribe_with<B>(
        self,
        build: B,
    ) -> Result<SubscribePrimingChunk<'a>, Error>
       where B: FnMut(SubscribeReqBuilder<SubscribeSender<'a>>) -> Result<SubscribeSender<'a>, Error> { ... }
    async fn subscribe_sender(self) -> Result<SubscribeSender<'a>, Error> { ... }
}
Expand description

IM Client trait — extension over an Exchange that adds the Matter Interaction Model client operations.

Implemented for Exchange<'a>; user code just uses this trait to get method-syntax access on any exchange handle. Two flavours of method live on this trait:

  • *_sender — hands the caller a typed *Sender they drive manually. Maximum control, full visibility into the retransmit loop and chunked response iteration.
  • *_with / *_with_async — takes a build closure that writes the request straight into the TX buffer; the retransmit loop is handled internally and the first response chunk is handed back for the caller to iterate via complete().

On top of these, the codegen-emitted per-cluster <ClusterName>Client<'a> traits add high-level single-shot methods (<cluster>_<command> / <cluster>_<attr>_read / <cluster>_<attr>_write) that bake in the cluster/attr/cmd IDs and the chunk-drain / status-to-error conversion for the common case.

The trait sits over Self: Into<Exchange<'a>> so any type that converts to an exchange can opt in via a one-line blanket impl; Exchange<'a> itself implements Into<Exchange<'a>> for free via the standard-library identity impl.

§Lifecycle

Every method consumes the exchange (self by value) — one exchange is one IM transaction, end of story. After the method returns, the exchange is closed and the slot is released; callers wanting to issue another transaction must initiate a fresh exchange.

Provided Methods§

Source

async fn read_with<B>(self, build: B) -> Result<ReadRespChunk<'a>, Error>

Perform an IM read transaction.

§Arguments
  • build closure that writes the ReadRequestMessage TLV body NOTE: The closure is FnMut because the MRP layer may retransmit the request multiple times; it MUST produce the same TLV output on every call.
§Returns
  • Ok(ReadRespChunk) for the first response chunk; multi-chunk ReportData streams iterate via ReadRespChunk::complete()
  • Err if the transaction fails at any point (request build, I/O, response parsing, etc.)
Source

async fn read_sender(self) -> Result<ReadSender<'a>, Error>

Perform an IM read transaction without using a closure.

§Returns
  • Ok(ReadSender) ready for the caller to drive manually via ReadSender::tx() The first call to ReadSender::tx yields the initial builder. See invoke_sender for the full pattern.
  • Err if the transaction fails at any point (I/O, etc.)
Source

async fn write_with<B>( self, timed_timeout_ms: Option<u16>, build: B, ) -> Result<WriteRespHandle<'a>, Error>

Perform an IM write transaction.

§Arguments
  • build closure that writes the WriteRequestMessage TLV body. NOTE: the closure is FnMut because the MRP layer may retransmit the request multiple times; it MUST produce the same TLV output on every call.
§Returns
  • Ok(WriteRespHandle) once the request is ACK-ed and the response is parsed; call WriteRespHandle::response() to inspect the parsed WriteResp.
  • Err if the transaction fails at any point (request build, I/O, response parsing, etc.)
Source

async fn write_sender( self, timed_timeout_ms: Option<u16>, ) -> Result<WriteSender<'a>, Error>

Perform an IM write transaction without using a closure.

§Arguments
  • timed_timeout_ms if Some, perform the initial handshake via a TimedRequest with the given timeout (in milliseconds)
§Returns
  • Ok(WriteSender) ready for the caller to drive manually via WriteSender::tx() The first call to WriteSender::tx yields the initial builder. See invoke_sender for the full pattern.
  • Err if the transaction fails at any point (I/O, etc.)
Source

async fn invoke_with<B>( self, timed_timeout_ms: Option<u16>, build: B, ) -> Result<InvokeRespChunk<'a>, Error>

Perform an IM invoke transaction.

§Arguments
  • timed_timeout_ms if Some, perform the initial handshake via a TimedRequest with the given timeout (in milliseconds)
  • build closure that writes the InvokeRequestMessage TLV body NOTE: The closure is FnMut because the MRP layer may retransmit the request multiple times; it MUST produce the same TLV output on every call.
§Returns
  • Ok(InvokeRespChunk) once the request is ACK-ed and the first response chunk is parsed; multi-chunk InvokeResponse streams iterate via InvokeRespChunk::complete().
  • Err if the transaction fails at any point (request build, I/O, response parsing, etc.)
Source

async fn invoke_sender( self, timed_timeout_ms: Option<u16>, ) -> Result<InvokeSender<'a>, Error>

Perform an IM invoke transaction without using a closure.

§Arguments
  • timed_timeout_ms if Some, perform the initial handshake via a TimedRequest with the given timeout (in milliseconds)
§Returns
  • Ok(InvokeSender) ready for the caller to drive manually via InvokeSender::tx(). The first call to InvokeSender::tx yields the initial builder.
  • Err if the transaction fails at any point (I/O, etc.)
§Lifecycle
  1. let mut sender = exchange.invoke_sender(None).await?;
  2. loop { match sender.tx().await? { TxOutcome::BuildRequest(b) => sender = build(b)?, TxOutcome::GotResponse(c) => break c } }
  3. loop { let resp = chunk.response()?; …; match chunk.complete().await? { … } }
Source

async fn subscribe_with<B>( self, build: B, ) -> Result<SubscribePrimingChunk<'a>, Error>

Perform the establishment phase of an IM subscribe transaction.

On the wire the establishment is a sequence of priming ReportData chunks (each ACK-ed by the client with StatusResponse(Success)) followed by a single SubscribeResponse carrying subscription_id and the chosen max_int. This method drives the request side and hands the caller back the first priming chunk; the caller iterates further priming chunks (and gets the terminal SubscribeEstablished) via SubscribePrimingChunk::complete.

§Arguments
  • build — closure that writes the SubscribeRequestMessage TLV body via the streaming SubscribeReqBuilder. NOTE: FnMut because the MRP layer may retransmit the request; it MUST produce the same TLV output on every call.
§Returns
  • Ok(SubscribePrimingChunk) for the first priming chunk; walk the chunk loop via SubscribePrimingChunk::complete.
  • Err on any failure (request build, I/O, response parsing, peer-side validation StatusResponse(non-Success), …)
§Scope: establishment only

The active subscription phase — server-initiated ReportData messages arriving on new exchanges throughout the lifetime of the subscription — is not covered by this method. That requires a listening loop on the fabric/peer-node pair and is a separate piece of infrastructure to layer on top. Once the SubscribeEstablished is returned, the fabric+peer+subscription-id triple identifies the active subscription for any such future incoming reports.

Source

async fn subscribe_sender(self) -> Result<SubscribeSender<'a>, Error>

Perform the establishment phase of an IM subscribe transaction without using a closure.

§Returns

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl<'a> ImClient<'a> for Exchange<'a>

Blanket impl so any Exchange<'a> is an ImClient<'a> when the trait is used. The default-method bodies do all the work; this impl just opts the type in.