Skip to main content

Commissioner

Struct Commissioner 

Source
pub struct Commissioner<'a, C>
where C: Crypto,
{ /* private fields */ }
Expand description

Stateful commissioner.

Holds the references needed for the whole flow so individual steps don’t have to take them. &mut NocGenerator because each commission() call mutably borrows the generator’s scratch buffer to write the device NOC into; &mut [u8] buf is a caller-owned scratch slice used to stage the fabric’s RCAC and ICAC bytes across the on-wire async calls (the fabric record itself can only be borrowed inside Matter::with_state, which doesn’t compose with await).

The controller’s fabric is expected to already be in matter.state.fabrics at the given fab_idx — the caller installs it once via crate::fabric::Fabrics::add before constructing any commissioner. A single Commissioner instance can then be reused to commission any number of devices onto that fabric.

Implementations§

Source§

impl<'a, C> Commissioner<'a, C>
where C: Crypto,

Source

pub const fn new( matter: &'a Matter<'a>, crypto: C, fab_idx: NonZero<u8>, noc_generator: &'a mut NocGenerator<'a>, buf: &'a mut [u8], ) -> Commissioner<'a, C>

Create a commissioner bound to a Matter stack, crypto backend, an already-installed fabric (fab_idx), an already-constructed NOC generator that signs against the chain stored on that fabric, and a scratch buffer.

buf is used to copy the fabric’s RCAC and (optionally) ICAC bytes out of the locked fabric table so they can be passed to the asynchronous AddTrustedRootCertificate / AddNOC invokes. It must be at least crate::cert::MAX_CERT_TLV_LEN bytes; the commissioner sequences the two transfers (RCAC first, then ICAC re-uses the same slot) so a single-cert worth of memory is enough.

Source

pub const fn fab_idx(&self) -> NonZero<u8>

Index of the controller’s fabric in matter.state.fabrics. The caller picked this when installing the fabric; the commissioner simply propagates it (e.g. into CommissionResult callers build on top).

Source

pub async fn commission( &mut self, peer_addr: Address, passcode: u32, opts: &CommissionOptions, device_node_id: u64, validity: Validity, ) -> Result<CommissionResult, Error>

Phase 1 — drive ArmFailSafe through AddNOC over PASE.

Pre-condition: PASE handshake against the device has completed successfully on matter’s transport. The function locates that PASE session by the (fab=0, peer=0, secure=true) lookup tuple every step uses — it implicitly assumes a single in-flight PASE session, which is the case in practice for a controller driving one device at a time.

device_node_id is the NodeID the caller wishes to assign to the device on the controller’s fabric. validity is the NOC’s validity window — typically crate::cert::gen::VALID_FOREVER for long-lived deployments, or a bounded window for short-lived re-issuance. The NOC’s ASN.1 serial number is derived from the NodeID (see NocGenerator::generate).

On success the device has accepted our RCAC + NOC and assigned us a CommissionResult::fabric_index, but its fail-safe is still armed and PASE is still live. Phase 2 (Self::complete_via_case) finalises commissioning over CASE; if the caller doesn’t run it before the fail-safe expires the device rolls back.

Source

pub async fn complete_via_case( &mut self, peer_addr: Address, phase1: &CommissionResult, ) -> Result<(), Error>

Phase 2 — establish CASE against the device’s freshly-installed operational identity and invoke CommissioningComplete over it.

peer_addr is the device’s operational endpoint. In production it’s discovered via _matter._tcp mDNS; in tests / examples it can be the same address PASE used, since the device announces on the same UDP port post-AddNOC.

Steps:

  1. Open a fresh plaintext exchange to peer_addr and run [CaseInitiator::initiate] (Sigma1 → Sigma2 → Sigma3 → StatusReport). On success the new CASE session is keyed in matter.state.sessions at (fab_idx, device_node_id, secure=true).
  2. Open a CASE-secured exchange on that session and invoke GeneralCommissioning::CommissioningComplete. The device disarms its fail-safe and persists the new fabric.
Source

pub async fn complete_via_case_operational( &mut self, phase1: &CommissionResult, ) -> Result<(), Error>

Phase 2, resolving the device’s operational address via mDNS.

Identical to Self::complete_via_case except that, instead of being handed a fixed peer_addr, it looks up the device’s operational endpoint via _matter._tcp mDNS from (fabric, device_node_id) (using Exchange::initiate_plaintext_operational).

This is the production phase-2 path: after phase 1 the device may only be reachable at a different address than PASE used - most notably when the device was commissioned over BLE and has since joined its operational (Wi-Fi / Thread) network, where its operational IP is not known until it announces itself. It requires the mDNS backend to be running (so the resolve request is answered), and the device to have joined the network and started announcing operationally.

Auto Trait Implementations§

§

impl<'a, C> !RefUnwindSafe for Commissioner<'a, C>

§

impl<'a, C> !Send for Commissioner<'a, C>

§

impl<'a, C> !Sync for Commissioner<'a, C>

§

impl<'a, C> !UnwindSafe for Commissioner<'a, C>

§

impl<'a, C> Freeze for Commissioner<'a, C>
where C: Freeze,

§

impl<'a, C> Unpin for Commissioner<'a, C>
where C: Unpin,

§

impl<'a, C> UnsafeUnpin for Commissioner<'a, C>
where C: UnsafeUnpin,

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, E> Init<T, E> for T

Source§

unsafe fn __init(self, slot: *mut T) -> Result<(), E>

Initializes slot. Read more
Source§

fn chain<F>(self, f: F) -> ChainInit<Self, F, T, E>
where F: FnOnce(&mut T) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. 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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T, I> IntoFallibleInit<T> for I
where I: Init<T>,

Source§

fn into_fallible<E>(self) -> impl Init<T, E>

Convert the infallible initializer to a fallible one.
Source§

impl<Source, Target> OctetsInto<Target> for Source
where Target: OctetsFrom<Source>,

Source§

type Error = <Target as OctetsFrom<Source>>::Error

Source§

fn try_octets_into( self, ) -> Result<Target, <Source as OctetsInto<Target>>::Error>

Performs the conversion.
Source§

fn octets_into(self) -> Target
where Self::Error: Into<Infallible>,

Performs an infallible conversion.
Source§

impl<T, E> PinInit<T, E> for T

Source§

unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E>

Initializes slot. Read more
Source§

fn pin_chain<F>(self, f: F) -> ChainPinInit<Self, F, T, E>
where F: FnOnce(Pin<&mut T>) -> Result<(), E>,

First initializes the value using self then calls the function f with the initialized value. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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