{"id":30178349,"url":"https://github.com/sysgrok/rs-matter-stack","last_synced_at":"2026-04-02T02:47:44.115Z","repository":{"id":241551991,"uuid":"805925504","full_name":"sysgrok/rs-matter-stack","owner":"sysgrok","description":"Easily configure and run rs-matter","archived":false,"fork":false,"pushed_at":"2025-07-23T09:53:28.000Z","size":300,"stargazers_count":11,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-31T19:39:46.272Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sysgrok.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-05-25T21:30:09.000Z","updated_at":"2025-07-31T11:24:47.000Z","dependencies_parsed_at":"2025-06-28T09:41:50.076Z","dependency_job_id":"d8b37061-a298-4a4e-a8d6-edacb704f354","html_url":"https://github.com/sysgrok/rs-matter-stack","commit_stats":{"total_commits":75,"total_committers":1,"mean_commits":75.0,"dds":0.0,"last_synced_commit":"820e36a8c47ee9dfb9cb9580b8681343b0f7121d"},"previous_names":["ivmarkov/rs-matter-stack","sysgrok/rs-matter-stack"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sysgrok/rs-matter-stack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Frs-matter-stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Frs-matter-stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Frs-matter-stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Frs-matter-stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sysgrok","download_url":"https://codeload.github.com/sysgrok/rs-matter-stack/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Frs-matter-stack/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270005591,"owners_count":24510939,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-12T05:20:35.137Z","updated_at":"2026-04-02T02:47:44.108Z","avatar_url":"https://github.com/sysgrok.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![alt text](https://avatars.githubusercontent.com/u/61027988?s=48\u0026v=4 \"rs-matter-stack\") Easily configure and run [rs-matter](https://github.com/project-chip/rs-matter)\n\n[![CI](https://github.com/ivmarkov/rs-matter-stack/actions/workflows/ci.yml/badge.svg)](https://github.com/ivmarkov/rs-matter-stack/actions/workflows/ci.yml)\n[![crates.io](https://img.shields.io/crates/v/rs-matter-stack.svg)](https://crates.io/crates/rs-matter-stack)\n[![Matrix](https://img.shields.io/matrix/matter-rs:matrix.org?label=join%20matrix\u0026color=BEC5C9\u0026logo=matrix)](https://matrix.to/#/#matter-rs:matrix.org)\n\n## Overview\n\nConfiguring the [`rs-matter`](https://github.com/project-chip/rs-matter) crate is not trivial, as it is more of a toolkit rather than a monolitic all-in-one runtime.\n\nFurthermore, _operating_ the assembled Matter stack is also challenging, as various features might need to be switched on or off depending on whether Matter is running in commissioning or operating mode, and also depending on the current network connectivity (as in e.g. Wifi signal lost).\n\n**This crate addresses these issues by providing an all-in-one [`MatterStack`](https://github.com/ivmarkov/rs-matter-stack/blob/master/src/lib.rs) assembly that configures `rs-matter` for reliable operation.**\n\nInstantiate it and then call `MatterStack::\u003c...\u003e::run(...)`.\n\n## OK, but what would I sacrifice?\n\n**Flexibility**.\n\nThe Matter stack is assembled as one large future which is not `Send`. Using an executor to poll that future together with others is still possible, but the executor should be a local one (i.e. Embassy's `embassy-executor`, Tokio's `LocalSet`, `async_executor::LocalExecutor` and so on).\n\n## The examples are STD-only?\n\nThe core of `rs-matter-stack` is `no_std` and no-`alloc`.\n\nYou need to provide platform-specific implementations of the following traits for your embedded platform:\n- `KvBlobStore` - non-volatile key-value storage abstraction.\n  - For STD, `rs-matter-stack` provides `DirKvBlobStore`.\n- `NetifDiag` - network interface abstraction (i.e. monitoring when the network interface is up or down, and what is its IP configuration).\n  - For Unix-like OSes, `rs-matter` provides `UnixNetifs`, which uses a simple polling every 2 seconds to detect changes to the network interface.\n  - Note that For IP (TCP \u0026 UDP) IO, the stack uses the [`edge-nal`](https://github.com/ivmarkov/edge-net/tree/master/edge-nal) crate, and is thus compatible with [`STD`](https://github.com/ivmarkov/edge-net/tree/master/edge-nal-std) and [`Embassy`](https://github.com/ivmarkov/edge-net/tree/master/edge-nal-embassy) out of the box. You only need to worry about networking IO if you use other platforms than these two.\n- Implementation of the UDP traits from [edge-nal](https://github.com/ivmarkov/edge-net/tree/master/edge-nal).\n  - There are out-of-the-box implementations for [Rust STD BSD sockets](https://github.com/ivmarkov/edge-net/tree/master/edge-nal-std) as well as for [`embassy-net`](https://github.com/ivmarkov/edge-net/tree/master/edge-nal-embassy) and for [OpenThread](https://github.com/ivmarkov/esp-openthread/blob/main/openthread/src/enal.rs).\n- `GattPeripheral` - BLE GATT peripheral abstraction of the device radio. Not necessary for Ethernet connectivity\n  - For Linux, `rs-matter` provides `BluerGattPeripheral`, which uses the Linux BlueZ BT stack.\n- `NetCtl` - Wifi controller implementation when using Wifi connectivity (Thread has a built-in one in OpenThread).\n  - `NoopWirelessNetCtl` is a no-op wireless implementation of a Wifi controller that is useful for testing. I.e. on Linux, one can use `PreexistingWireless` + `NoopWirelessNetCtl` together with `BluerGattPeripheral` and `UnixNetifs` to test the stack in wireless mode. For production embedded Linux use-cases, you'll have to provide a true `NetCtl` implementation, possibly based on WPA Supplicant, or NetworkManager (which **are** in the meantime both available from upstream `rs-matter`).\n\n## Embassy\n\nThe [`rs-matter-embassy`](https://github.com/ivmarkov/rs-matter-embassy) crate provides implementations for `KvBlobStore`, `NetifDiag`, `NetCtl`, `GattPeripheral` and others for the [`embassy`](https://github.com/embassy-rs/embassy) framework.\n\n## ESP-IDF\n\nThe [`esp-idf-matter`](https://github.com/ivmarkov/esp-idf-matter) crate provides implementations for `KvBlobStore`, `NetifDiag`, `GattPeripheral` and others for the [ESP-IDF SDK](https://github.com/esp-rs/esp-idf-svc).\n\n## Example\n\n(See also [All examples](#all-examples))\n\n```rust\n//! An example utilizing the `EthMatterStack` struct.\n//! As the name suggests, this Matter stack assembly uses Ethernet as the main transport,\n//! as well as for commissioning.\n//!\n//! Notice that it might be that rather than Ethernet, the actual L2 transport is Wifi.\n//! From the POV of Matter - this case is indistinguishable from Ethernet as long as the\n//! Matter stack is not concerned with connecting to the Wifi network, managing\n//! its credentials etc. and can assume it \"pre-exists\".\n//!\n//! The example implements a fictitious Light device (an On-Off Matter cluster).\n#![recursion_limit = \"256\"]\n\nuse core::pin::pin;\n\nuse log::info;\n\nuse rs_matter::crypto::{default_crypto, Crypto};\nuse rs_matter::dm::clusters::on_off::test::TestOnOffDeviceLogic;\nuse rs_matter::dm::clusters::on_off::OnOffHooks;\nuse rs_matter::dm::devices::test::DAC_PRIVKEY;\nuse rs_matter_stack::eth::EthMatterStack;\nuse rs_matter_stack::matter::dm::clusters::desc;\nuse rs_matter_stack::matter::dm::clusters::desc::ClusterHandler as _;\nuse rs_matter_stack::matter::dm::clusters::on_off;\nuse rs_matter_stack::matter::dm::devices::test::{TEST_DEV_ATT, TEST_DEV_COMM, TEST_DEV_DET};\nuse rs_matter_stack::matter::dm::devices::DEV_TYPE_ON_OFF_LIGHT;\nuse rs_matter_stack::matter::dm::networks::unix::UnixNetifs;\nuse rs_matter_stack::matter::dm::{Async, Dataver, Endpoint, Node};\nuse rs_matter_stack::matter::dm::{EmptyHandler, EpClMatcher};\nuse rs_matter_stack::matter::error::Error;\nuse rs_matter_stack::matter::utils::init::InitMaybeUninit;\nuse rs_matter_stack::matter::{clusters, devices};\nuse rs_matter_stack::mdns::ZeroconfMdns;\nuse rs_matter_stack::persist::DirKvBlobStore;\n\nuse static_cell::StaticCell;\n\n/// The amount of memory for allocating all `rs-matter-stack` futures created during\n/// the execution of the `run*` methods.\n/// This does NOT include the rest of the Matter stack.\n///\n/// The futures of `rs-matter-stack` created during the execution of the `run*` methods\n/// are allocated in a special way using a small bump allocator which results\n/// in a much lower memory usage by those.\n///\n/// If - for your platform - this size is not enough, increase it until\n/// the program runs without panics during the stack initialization.\nconst BUMP_SIZE: usize = 20000;\n\nfn main() -\u003e Result\u003c(), Error\u003e {\n    env_logger::init_from_env(\n        env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, \"info\"),\n    );\n\n    info!(\"Starting...\");\n\n    // Initialize the Matter stack (can be done only once),\n    // as we'll run it in this thread\n    let stack = MATTER_STACK\n        .uninit()\n        .init_with(EthMatterStack::init_default(\n            \u0026TEST_DEV_DET,\n            TEST_DEV_COMM,\n            \u0026TEST_DEV_ATT,\n        ));\n\n    // The default crypto provider\n    let crypto = default_crypto(rand::thread_rng(), DAC_PRIVKEY);\n\n    let mut rand = crypto.weak_rand()?;\n\n    // Our \"light\" on-off cluster.\n    // It will toggle the light state every 5 seconds\n    let on_off = on_off::OnOffHandler::new_standalone(\n        Dataver::new_rand(\u0026mut rand),\n        LIGHT_ENDPOINT_ID,\n        TestOnOffDeviceLogic::new(true),\n    );\n\n    // Chain our endpoint clusters with the\n    // (root) Endpoint 0 system clusters in the final handler\n    let handler = EmptyHandler\n        .chain(\n            EpClMatcher::new(\n                Some(LIGHT_ENDPOINT_ID),\n                Some(TestOnOffDeviceLogic::CLUSTER.id),\n            ),\n            on_off::HandlerAsyncAdaptor(\u0026on_off),\n        )\n        // Each Endpoint needs a Descriptor cluster too\n        // Just use the one that `rs-matter` provides out of the box\n        .chain(\n            EpClMatcher::new(Some(LIGHT_ENDPOINT_ID), Some(desc::DescHandler::CLUSTER.id)),\n            Async(desc::DescHandler::new(Dataver::new_rand(\u0026mut rand)).adapt()),\n        );\n\n    // Create the persister \u0026 load any previously saved state\n    let persist = futures_lite::future::block_on(\n        stack.create_persist_with_comm_window(\u0026crypto, DirKvBlobStore::new_default()),\n    )?;\n\n    // Run the Matter stack with our handler\n    // Using `pin!` is completely optional, but reduces the size of the final future\n    let matter = pin!(stack.run_preex(\n        // The Matter stack needs UDP sockets to communicate with other Matter devices\n        edge_nal_std::Stack::new(),\n        // Will try to find a default network interface\n        UnixNetifs,\n        // Will use the mDNS implementation based on the `zeroconf` crate\n        ZeroconfMdns,\n        // Will persist in `\u003ctmp-dir\u003e/rs-matter`\n        \u0026persist,\n        // The crypto provider\n        \u0026crypto,\n        // Our `AsyncHandler` + `AsyncMetadata` impl\n        (NODE, handler),\n        // No user task future to run\n        (),\n    ));\n\n    // Schedule the Matter run\n    futures_lite::future::block_on(matter)\n}\n\n/// The Matter stack is allocated statically to avoid\n/// program stack blowups.\nstatic MATTER_STACK: StaticCell\u003cEthMatterStack\u003cBUMP_SIZE, ()\u003e\u003e = StaticCell::new();\n\n/// Endpoint 0 (the root endpoint) always runs\n/// the hidden Matter system clusters, so we pick ID=1\nconst LIGHT_ENDPOINT_ID: u16 = 1;\n\n/// The Matter Light device Node\nconst NODE: Node = Node {\n    id: 0,\n    endpoints: \u0026[\n        EthMatterStack::\u003c0, ()\u003e::root_endpoint(),\n        Endpoint {\n            id: LIGHT_ENDPOINT_ID,\n            device_types: devices!(DEV_TYPE_ON_OFF_LIGHT),\n            clusters: clusters!(desc::DescHandler::CLUSTER, TestOnOffDeviceLogic::CLUSTER),\n        },\n    ],\n};\n```\n\n## All examples\n\nTo build all examples, use:\n\n```\ncargo build --examples --features examples\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsysgrok%2Frs-matter-stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsysgrok%2Frs-matter-stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsysgrok%2Frs-matter-stack/lists"}