Skip to main content

Crate matc

Crate matc 

Source
Expand description

Matter controller library

This library allows to controll Matter compatible devices. Library uses asynchronous Rust and depends on Tokio. Following are main parts of api:

  • Transport - Representation of IP/UDP transport. Binds to specified IP/port, allows to define virtual connections for remote destinations and demultiplexes incoming messages based on these connections.
  • CertManager - Trait allowing to supply external certificate storage. Default implementation certmanager::FileCertManager stores certificates to specified directory in PEM format.
  • Controller - Matter controller - uses Transport to send/receive messages, CertManager to get certificates. Allows to commission device, authenticate commissioned device. Authenticated device is represented by Connection which allows to read attributes and invoke commands.
  • tlv - Module with simple matter tlv encoders and decoders which can be used to encode command parameters and decode complex responses.
  • im - Typed Interaction Model report layer - decoded attribute/event reports used by Connection::read_request2 and the subscription API (Connection::subscribe_attrs returns a Subscription delivering decoded updates).
  • discover - simple mdns based discovery of matter devices on local network
  • devman - High level device manager which uses all above components to provide simpler api. It stores device information and certificates in specified directory and allows to commission new devices (by address, by manual pairing code with mDNS discovery, or over BLE with Wi-Fi/Thread credential provisioning - requires ble feature) and connect to already commissioned devices by name. Connections automatically re-discover devices via operational mDNS if the stored address is stale (e.g. device changed IP).
  • clusters - matter cluster definitions and encoders/decoders for cluster attributes and commands.

Examples directory contains simple demo application and simple standalone examples on how to use APIs.

Library can be used through high level device manager api or through lower level controller and transport apis. Device manager api is simpler to use, but does not provide same flexibility like lower level apis. For example how to use device manager see simple-devman.rs and devman_demo.rs examples in examples directory.

Example how to initialize device manager

const FABRIC_ID: u64 = 100;
const CONTROLLER_ID: u64 = 200;
const LOCAL_ADDRESS: &str = "0.0.0.0:5555";
const DATA_DIR: &str = "./matter-data";
let config = ManagerConfig {
            fabric_id: FABRIC_ID,
            controller_id: CONTROLLER_ID,
            local_address: LOCAL_ADDRESS.to_string(),
};
let devman = DeviceManager::create(DATA_DIR, config).await?;

Example how to load existing device manager configuration and commission device using it. Shows both ways to talk to the device - typed facade (recommended) and raw API:

const CONTROLLER_ID: u64 = 200;
const NODE_ID: u64 = 300;
const NAME: &str = "My Device";
const DATA_DIR: &str = "./matter-data";
const PIN: u32 = 123456;
let devman = DeviceManager::load(DATA_DIR).await?;
let device = devman.commission("1.1.1.1:5540", PIN, NODE_ID, NAME).await?;

// Option A - typed facade: one call per command / attribute, typed args and return value.
on_off::on(&device, 1).await?;
let state: bool = on_off::read_on_off(&device, 1).await?;

// Option B - raw API: cluster/command IDs + raw TLV payload. Useful when the cluster
// is not covered by the facade or when the payload is built dynamically at runtime.
device.invoke_request(1, clusters::defs::CLUSTER_ID_ON_OFF, clusters::defs::CLUSTER_ON_OFF_CMD_ID_ON, &[]).await?;

Example how to commission device using manual pairing code (mDNS discovery happens automatically):

const DATA_DIR: &str = "./matter-data";
let devman = DeviceManager::load(DATA_DIR).await?;
let device = devman.commission_with_code("0251-520-0076", 300, "My Device").await?;

Example how to commission a Wi-Fi device that advertises over BLE (requires ble feature):

const DATA_DIR: &str = "./matter-data";
let devman = DeviceManager::load(DATA_DIR).await?;
let device = devman.commission_ble_with_code(
    "MT:Y.K908...",   // QR or manual pairing code
    300,              // node ID to assign
    "kitchen light",  // friendly name
    NetworkCreds::WiFi {
        ssid: b"HomeWifi".to_vec(),
        creds: b"secret".to_vec(),
    },
).await?;

Example how to connect to already commissioned device by name and send command to it. If the device changed its IP, the connection automatically re-discovers it via operational mDNS:

const DATA_DIR: &str = "./matter-data";
const NAME: &str = "My Device";
let devman = DeviceManager::load(DATA_DIR).await?;
let device = devman.connect_by_name(NAME).await?;
device.invoke_request(1, clusters::defs::CLUSTER_ID_ON_OFF, clusters::defs::CLUSTER_ON_OFF_CMD_ID_ON, &[]).await?;

Following are examples how to use lower level APIs without device manager.

Example how to initialize certificate authority and create controller user - stores certificates in pem directory:

let fabric_id = 1000;
let controller_id = 100;
let cm = FileCertManager::new(fabric_id, "./pem");
cm.bootstrap()?;
cm.create_user(controller_id)?;

Example how to commission device using certificates pre-created in pem directory:

let fabric_id = 1000;
let device_id = 300;
let controller_id = 100;
let pin = 123456;
let cm: Arc<dyn certmanager::CertManager> = certmanager::FileCertManager::load("./pem")?;
let transport = transport::Transport::new("0.0.0.0:5555").await?;
let controller = controller::Controller::new(&cm, &transport, fabric_id)?;
let connection = transport.create_connection("1.2.3.4:5540").await;
let mut connection = controller.commission(&connection, pin, device_id, controller_id).await?;
// commission method returns authenticated connection which can be used to send commands
// now we can send ON command:
connection.invoke_request(1,  // endpoint
                          clusters::defs::CLUSTER_ID_ON_OFF,
                          clusters::defs::CLUSTER_ON_OFF_CMD_ID_ON,
                          &[]).await?;

Example sending ON command to device which is already commissioned using certificates pre-created in pem directory:

let fabric_id = 1000;
let device_id = 300;
let controller_id = 100;
let cm: Arc<dyn certmanager::CertManager> = certmanager::FileCertManager::load("./pem")?;
let transport = transport::Transport::new("0.0.0.0:5555").await?;
let controller = controller::Controller::new(&cm, &transport, fabric_id)?;
let connection = transport.create_connection("1.2.3.4:5540").await;
let mut c = controller.auth_sigma(&connection, device_id, controller_id).await?;
// send ON command
c.invoke_request(1, // endpoint
                 clusters::defs::CLUSTER_ID_ON_OFF,
                 clusters::defs::CLUSTER_ON_OFF_CMD_ID_ON,
                 &[]).await?;
//
// invoke SetLevel command to show how to supply command parameters
let tlv = tlv::TlvItemEnc {
  tag: 0,
  value: tlv::TlvItemValueEnc::StructInvisible(vec![
    tlv::TlvItemEnc { tag: 0, value: tlv::TlvItemValueEnc::UInt8(50)   }, // level
    tlv::TlvItemEnc { tag: 1, value: tlv::TlvItemValueEnc::UInt16(1000)}, // transition time
    tlv::TlvItemEnc { tag: 2, value: tlv::TlvItemValueEnc::UInt8(0)    }, // options mask
    tlv::TlvItemEnc { tag: 3, value: tlv::TlvItemValueEnc::UInt8(0)    }, // options override
  ])
}.encode()?;
c.invoke_request(1, // endpoint
                 clusters::defs::CLUSTER_ID_LEVEL_CONTROL,
                 clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_MOVETOLEVEL,
                 &tlv).await?;
//
// read level
let result = c.read_request2(1,
                             clusters::defs::CLUSTER_ID_LEVEL_CONTROL,
                             clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_CURRENTLEVEL,
                             ).await?;
println!("{:?}", result);

§Cluster access: typed facade vs. raw API

The examples above use a mix of two styles for talking to a cluster on a connected device. Both are supported and can be mixed freely on the same Connection:

  1. Typed facade (recommended for known clusters) - each generated cluster module in clusters::codec exposes one pub async fn per command and one read_<attr> per attribute. Calls take &Connection, endpoint, ...args and do encode+invoke+decode (or read+decode) in a single step, with typed parameters and typed return values (Result<()> for ACK-only commands, Result<FooResponse> for commands with a response struct, the decoder’s native Rust type for attributes). See examples/simple.rs for a minimal end-to-end usage.

    use matc::clusters::codec::on_off;
    on_off::on(&conn, 1).await?;
    let state: bool = on_off::read_on_off(&conn, 1).await?;
  2. Raw API (for dynamic / untyped / debugging use) - the facade is an alternative, not a replacement. The lower-level Connection::invoke_request / Connection::read_request2 methods take cluster/command/attribute IDs from clusters::defs and raw TLV byte payloads, and return the raw response TLV. Use this when you need to:

    • talk to a cluster or field not covered by the generated facade,
    • build command payloads dynamically at runtime (e.g. a generic CLI or REPL - see examples/demo.rs and examples/shell.rs),
    • inspect the raw response TLV (e.g. res.tlv.dump(1) for protocol-level debugging),
    • use invoke_request_timed and other specialized paths the facade does not wrap.

§simple rust matter protocol library

build doc

This is matter protocol library in rust (controller side).

API doc

Examples

Matter controller desktop application also demonstrates use of this library

It supports controller side of:

  • PASE - passcode authenticated session establishment
  • CASE - certificate authenticated session establishment
  • Commissioning procedure
    • sign and push certificates to device
    • BLE commissioning with Wi-Fi/Thread credential provisioning (opt-in, --features ble)
  • Basic interactions
    • Read/Write attributes
    • Invoke commands
    • Subscribe for notifications

See examples for usage, including the high-level devman_demo, BLE commissioning, and the low-level demo CLI.

Modules§

cert_matter
Handling of certificates in Matter format
cert_x509
Handling of x509 certificate compatible with matter
certmanager
Certificate manager trait and default file based implementation
clusters
Matter cluster definitions and related utilities.
controller
device
very experimental device implementation with many things hardcoded for testing and development purposes.
devman
Device manager for simplified Matter device interaction.
discover
Module with very simple mdns based discovery of matter devices. Usually application shall discover devices using these methods and filter according discriminator. This module tries to send mdns using ipv4 and ipv6 multicast at same time. If more control over discovery mechanism is required, it may be better to use some external mdns library.
fabric
im
Typed Interaction Model report layer.
mdns
Very simple mdns client library
mdns2
minimal mDNS service with continuous discovery, record caching, and service registration.
messages
mrp
Message Reliability Protocol (MRP) timing parameters and backoff math per Matter specification section 4.12.
onboarding
spake2p
tlv
Utilities to decode/encode matter tlv
transport
util

Enums§

NetworkCreds
Credentials for the network the device should join after commissioning.