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.
  • 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 and connect to already commissioned devices by name without worrying about certificates and transport details.
  • 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:

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?;
// now we can use device connection to send commands and read attributes
device.invoke_request(1, clusters::defs::CLUSTER_ID_ON_OFF, clusters::defs::CLUSTER_ON_OFF_CMD_ID_ON, &[]).await?;

Example how to connect to already commissioned device by name and send command to it:

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);

§simple rust matter protocol library

build doc

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

API doc

Examples

It supports controller side of:

  • PASE - passcode authenticated session establishment
  • CASE - certificate authenticated session establishment
  • Commisioning procedure
    • sign and push certificates to device
  • Basic interactions
    • Read attribute
    • Invoke command

This library expects that device is already reachable using IPV4 or IPV6. Bluetooth/BLE related communication is not yet supported. To control device which first requires commissioning using BLE, you must first commission using different controller (such as phone), then using that controller enable commissioning. For example in iphone/ios this is available under “enable pairing mode” in device settings in Home app. It will show “manual pairing code” which can be decoded to obtain commissioning pass code (see decode-manual-pairing-code bellow).

Use of demo application:

  • Compile demo application using cargo. Binary will be found usually in target/debug/examples/demo.
    cargo build --example demo

  • demo application uses clap. use –help to learn all supported parameters

  • create CA certificates in directory pem:
    ./demo ca-bootstrap

  • create key/certificate for controller with id 100:
    ./demo ca-create-controller 100

  • discover all commissionable devices using mdns:
    ./demo discover commissionable --timeout 3

  • discover all commissioned devices using mdns:
    ./demo discover commissioned --timeout 3

  • discover specific device commissioned by us. query will filter based on device-id and “our” fabric:
    ./demo discover commissioned2 --timeout 3 --device-id 300

  • if you have manual pairing code you can extract passcode from it using following command:
    demo decode-manual-pairing-code 1577-384-0075

  • commission device (device ip address is 192.168.5.70, commissioning passcode is 123456, device id will be 300, device admin has id 100):
    ./demo commission 192.168.5.70:5540 100 300 123456

  • update fabric label in device:
    ./demo command invoke-command-update-fabric-label --device-address 192.168.5.70:5540 --controller-id 100 --device-id 300 "testfabric"

  • example how to use read command to read any attribute. This example lists all provisioned fabrics by reading attribute 1(fabrics) from cluster 62 (operational credentials) from endpoint 0:
    ./demo command read --device-address 192.168.5.70:5540 --controller-id 100 --device-id 300 0 62 1

  • example which will list all attributes in all clusters for all endpoints supported by device ./demo command list-attributes --device-address 192.168.5.70:5540 --controller-id 100 --device-id 300

  • turn device on/off:
    demo command invoke-command-on --device-address 192.168.5.70:5540 --controller-id 100 --device-id 300

    demo command invoke-command-off --device-address 192.168.5.70:5540 --controller-id 100 --device-id 300

  • if you want to start from scratch remove directory pem

Other demo application flags:

  • –verbose - enable verbose logs
  • –local-address - specify local bind address for matter protocol. Format is ip:port. This is ip/port which is used as source address for matter UDP requests. Default is 0.0.0.0:5555. When IPV6 is used this must be changed for example to –local-address “[::]:5555”
  • –cert-path - change directory where pem files with keys and certificates are stored

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
mdns
Very simple mdns client library
mdns2
minimal mDNS service with continuous discovery, record caching, and service registration.
messages
onboarding
spake2p
tlv
Utilities to decode/encode matter tlv
transport
util