Skip to main content

matter_controller/
lib.rs

1//! The high-level Matter controller API — the single crate a consumer depends
2//! on to commission and control Matter devices from pure Rust.
3//!
4//! [`MatterController`] is the entry point. It persists a fabric and a stable
5//! commissioner identity through a pluggable [`ControllerStore`] (a default
6//! [`FileStore`] ships), commissions devices over IP, and exposes each device
7//! through a cheap [`Node`] handle that transparently establishes, caches, and
8//! reuses the operational CASE session.
9//!
10//! # Capabilities
11//!
12//! - **Fabric & identity** — [`MatterController::create_fabric`] mints and
13//!   persists the controller's stable operational identity once per fabric.
14//! - **Commissioning** — [`MatterController::commission`] brings a device onto
15//!   the fabric from a QR (`MT:…`) or manual pairing code, verifying device
16//!   attestation against the configured [`AttestationTrust`].
17//! - **Interaction** — [`Node::read`] / [`Node::write`] / [`Node::invoke`] work
18//!   over raw [`Value`]s and support **wildcard reads** ([`ReadPath::cluster`],
19//!   [`ReadPath::all`]) for reading every attribute off a device.
20//! - **Subscriptions** — [`Node::subscribe`] returns a [`Subscription`] stream
21//!   of [`SubscriptionEvent`]s (`Report` / `Established` / `Resubscribing` /
22//!   `Lagged`; `next().await` + `cancel()`).
23//! - **Multi-admin / commissioning windows** — [`Node::open_commissioning_window`]
24//!   opens an enhanced commissioning window (generates secrets, computes the PAKE
25//!   verifier, returns a [`CommissioningWindow`] with `manual_code`/`qr_code`);
26//!   [`Node::open_basic_commissioning_window`] opens a basic window; and
27//!   [`Node::revoke_commissioning`] closes any open window.
28//!   [`Node::commissioning_window_status`] reads the current window state.
29//! - **Fabric management** — [`Node::list_fabrics`] reads the device's full
30//!   fabric table as [`Vec<FabricDescriptor>`]; [`Node::remove_fabric`] removes a
31//!   fabric by index (self-protected: returns [`Error::WouldRemoveSelf`] for our
32//!   own fabric); [`Node::update_fabric_label`] relabels the accessing fabric.
33//! - **ACL management** — [`Node::read_acl`] returns the device's
34//!   `AccessControl.Acl` list as [`Vec<AclEntry>`]; [`Node::write_acl`] replaces it
35//!   atomically (single-chunk) or via a multi-chunk `MoreChunkedMessages` sequence
36//!   (large lists), with a lockout guard that returns [`Error::AclWouldLockOut`]
37//!   before sending any bytes if the new list would drop our own Administer/CASE
38//!   access.
39//! - **Group provisioning** — [`Node::write_group_key_set`] provisions a key set
40//!   on the device (`KeySetWrite`, `GroupKeyManagement` cluster 0x003F);
41//!   [`Node::write_group_key_map`] writes the `GroupKeyMap` attribute via the
42//!   chunked list-write mechanism; [`Node::add_group`] / [`Node::remove_group`]
43//!   add and remove an endpoint from a group (`Groups` cluster 0x0004). Public
44//!   types: [`GroupKeySet`] and [`GroupKeyMapEntry`].
45//! - **Group multicast send** — [`MatterController::create_group`] generates and
46//!   persists a group epoch key (returns a [`GroupKeySet`] ready to program onto
47//!   member devices); [`MatterController::invoke_group`] sends a fire-and-forget
48//!   group command over IPv6 multicast (`ff35:…`), encrypted with the operational
49//!   group key derived from the persisted epoch key. Returns `Ok` on datagram
50//!   send; there is no acknowledgement. [`Error::GroupNotProvisioned`] when the
51//!   key set has not been created via `create_group`.
52//!
53//! # Quickstart
54//!
55//! ```no_run
56//! use std::sync::Arc;
57//! use matter_controller::{
58//!     AttestationTrust, FabricConfig, FileStore, MatterController, MatterTime, ReadPath,
59//!     SubscriptionEvent,
60//! };
61//!
62//! # async fn run() -> Result<(), matter_controller::Error> {
63//! // Persisted store + attestation trust (test roots shown; use
64//! // `AttestationTrust::from_dirs(..)` with production PAA/CD roots for
65//! // certified devices).
66//! let store = Arc::new(FileStore::new("controller-state.bin"));
67//! let controller = MatterController::builder(store)
68//!     .attestation_trust(AttestationTrust::csa_test_roots())
69//!     .build()
70//!     .await?;
71//!
72//! // One-time: create the fabric (idempotent across restarts — load the
73//! // snapshot instead of re-creating in real apps).
74//! let fabric_id = controller.create_fabric(FabricConfig::new(
75//!     1,
76//!     1,
77//!     1,
78//!     (MatterTime::from_unix_secs(0), MatterTime::NO_EXPIRY),
79//! )).await?;
80//! let _ = fabric_id;
81//!
82//! // Commission a device, then control it.
83//! let node_id = controller.commission("MT:Y.K90AFN00KA0648G00").await?;
84//! let node = controller.node(node_id);
85//!
86//! // Read all attributes of the OnOff cluster (0x0006) on endpoint 1.
87//! let report = node.read(&[ReadPath::cluster(1, 0x0006)]).await?;
88//! for (path, value) in report {
89//!     println!("{path:?} = {value:?}");
90//! }
91//!
92//! // Subscribe to live changes.
93//! let mut sub = node.subscribe(&[ReadPath::cluster(1, 0x0006)], &[], 1, 30).await?;
94//! while let Some(event) = sub.next().await {
95//!     if let SubscriptionEvent::Report(change) = event {
96//!         println!("changed: {:?} = {:?}", change.path, change.value);
97//!     }
98//! }
99//! # Ok(())
100//! # }
101//! ```
102//!
103//! Migrating from matter.js? See `docs/matter-js-migration-guide.md`.
104
105#![forbid(unsafe_code)]
106
107pub(crate) mod acl;
108pub(crate) mod actor;
109pub(crate) mod admin;
110pub(crate) mod binding;
111#[cfg(feature = "ble")]
112pub(crate) mod ble_commission;
113pub mod builder;
114pub(crate) mod commission;
115pub mod controller;
116pub(crate) mod credentials;
117pub mod error;
118pub mod fabric;
119pub(crate) mod group;
120pub(crate) mod handshake_socket;
121pub(crate) mod icd;
122pub(crate) mod icd_listener;
123pub mod node;
124pub(crate) mod opcreds;
125pub mod provider_server;
126pub(crate) mod resumption;
127pub mod snapshot;
128pub mod state;
129pub mod store;
130pub mod subscription;
131pub mod trust;
132
133pub use acl::{AclAuthMode, AclEntry, AclPrivilege, AclTarget};
134pub use admin::{
135    CommissioningWindow, CommissioningWindowStatus, OpenWindowOpts, WindowStatus,
136    DEFAULT_WINDOW_ITERATIONS, DEFAULT_WINDOW_TIMEOUT_S,
137};
138pub use binding::BindingTarget;
139pub use builder::MatterControllerBuilder;
140pub use controller::MatterController;
141pub use error::Error;
142pub use fabric::{create_fabric, FabricConfig};
143pub use group::{GroupKeyMapEntry, GroupKeySet};
144pub use icd::{IcdClientType, IcdRegistration};
145pub use icd_listener::CheckIn;
146pub use matter_cert::MatterTime;
147pub use matter_codec::Value;
148/// Network (Wi-Fi/Thread) credentials for `MatterController::commission_ble`
149/// (feature `ble`), re-exported from `matter-commissioning`.
150pub use matter_commissioning::{NetworkCredentials, ThreadDataset, WiFiCredentials};
151pub use matter_interaction::{
152    AttributePath, CommandPath, EventFilter, EventPath, EventPriority, EventReport,
153    EventReportItem, EventTimestamp, ImStatus, ReadPath,
154};
155pub use node::{DstOffsetEntry, InvokeResult, Node, TimeGranularity, TimeZoneEntry};
156pub use opcreds::FabricDescriptor;
157pub use provider_server::{build_operational_service, ProviderServer};
158pub use state::{
159    CommissionerIdentity, ControllerState, DeviceEntry, FabricEntry, GroupKeySetConfig,
160};
161pub use store::{ControllerStore, FileStore, StoreError};
162pub use subscription::{AttributeReport, Subscription, SubscriptionEvent};
163pub use trust::AttestationTrust;