{"id":30178337,"url":"https://github.com/sysgrok/esp-idf-matter","last_synced_at":"2025-08-12T05:20:33.441Z","repository":{"id":236315983,"uuid":"792365901","full_name":"sysgrok/esp-idf-matter","owner":"sysgrok","description":"Run rs-matter on Espressif chips with ESP IDF","archived":false,"fork":false,"pushed_at":"2025-08-11T15:15:30.000Z","size":250,"stargazers_count":47,"open_issues_count":2,"forks_count":5,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-08-11T15:23:28.905Z","etag":null,"topics":["embedded","esp-idf","esp32","matter","rs-matter"],"latest_commit_sha":null,"homepage":"https://github.com/ivmarkov/esp-idf-matter","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":"CHANGELOG.md","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-04-26T14:18:50.000Z","updated_at":"2025-08-03T19:07:20.000Z","dependencies_parsed_at":"2024-06-16T06:44:29.932Z","dependency_job_id":"bda1422e-4a41-49bb-acf8-49b37836d535","html_url":"https://github.com/sysgrok/esp-idf-matter","commit_stats":{"total_commits":75,"total_committers":1,"mean_commits":75.0,"dds":0.0,"last_synced_commit":"ba27ed0e9763481b64f06ca8a8f588e623ef2560"},"previous_names":["ivmarkov/esp-idf-matter","sysgrok/esp-idf-matter"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sysgrok/esp-idf-matter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Fesp-idf-matter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Fesp-idf-matter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Fesp-idf-matter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Fesp-idf-matter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sysgrok","download_url":"https://codeload.github.com/sysgrok/esp-idf-matter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sysgrok%2Fesp-idf-matter/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":["embedded","esp-idf","esp32","matter","rs-matter"],"created_at":"2025-08-12T05:20:32.337Z","updated_at":"2025-08-12T05:20:33.421Z","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 \"esp-idf-matter\") Run [rs-matter](https://github.com/project-chip/rs-matter) on Espressif chips with [ESP-IDF](https://github.com/esp-rs/esp-idf-svc)\n\n[![CI](https://github.com/ivmarkov/esp-idf-matter/actions/workflows/ci.yml/badge.svg)](https://github.com/ivmarkov/esp-idf-matter/actions/workflows/ci.yml)\n[![crates.io](https://img.shields.io/crates/v/esp-idf-matter.svg)](https://crates.io/crates/esp-idf-matter)\n[![Documentation](https://img.shields.io/badge/docs-esp--rs-brightgreen)](https://ivmarkov.github.io/esp-idf-matter/esp_idf_matter/index.html)\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\nEverything necessary to run [`rs-matter`](https://github.com/project-chip/rs-matter) on the ESP-IDF:\n* Bluedroid implementation of `rs-matter`'s `GattPeripheral` for BLE comissioning support.\n* [`rs-matter-stack`](https://github.com/ivmarkov/rs-matter-stack) support with `Netif`, `Ble`, `Wireless` and `KvBlobStore` implementations.\n\nSince ESP-IDF does support the Rust Standard Library, UDP networking just works.\n\n## Example\n\n(See also [All examples](#all-examples))\n\n```rust\n//! An example utilizing the `EspWifiMatterStack` struct.\n//!\n//! As the name suggests, this Matter stack assembly uses Wifi as the main transport,\n//! and thus BLE for commissioning.\n//!\n//! If you want to use Ethernet, utilize `EspEthMatterStack` instead.\n//! If you want to use concurrent commissioning, call `run_coex` instead of just `run`.\n//! (Note: Alexa does not work (yet) with non-concurrent commissioning.)\n//!\n//! The example implements a fictitious Light device (an On-Off Matter cluster).\n#![allow(unexpected_cfgs)]\n#![recursion_limit = \"256\"]\n\nuse core::pin::pin;\n\nuse embassy_futures::select::select;\nuse embassy_time::{Duration, Timer};\n\nuse esp_idf_matter::init_async_io;\nuse esp_idf_matter::matter::dm::clusters::desc::{self, ClusterHandler as _, DescHandler};\nuse esp_idf_matter::matter::dm::clusters::on_off::{ClusterHandler as _, OnOffHandler};\nuse esp_idf_matter::matter::dm::devices::test::{TEST_DEV_ATT, TEST_DEV_COMM, TEST_DEV_DET};\nuse esp_idf_matter::matter::dm::devices::DEV_TYPE_ON_OFF_LIGHT;\nuse esp_idf_matter::matter::dm::{Async, Dataver, EmptyHandler, Endpoint, EpClMatcher, Node};\nuse esp_idf_matter::matter::utils::init::InitMaybeUninit;\nuse esp_idf_matter::matter::utils::select::Coalesce;\nuse esp_idf_matter::matter::{clusters, devices};\nuse esp_idf_matter::wireless::{EspMatterWifi, EspWifiMatterStack};\n\nuse esp_idf_svc::eventloop::EspSystemEventLoop;\nuse esp_idf_svc::hal::peripherals::Peripherals;\nuse esp_idf_svc::hal::task::block_on;\nuse esp_idf_svc::log::EspLogger;\nuse esp_idf_svc::nvs::EspDefaultNvsPartition;\nuse esp_idf_svc::timer::EspTaskTimerService;\n\nuse log::{error, info};\n\nuse static_cell::StaticCell;\n\nfn main() -\u003e Result\u003c(), anyhow::Error\u003e {\n    EspLogger::initialize_default();\n\n    info!(\"Starting...\");\n\n    // Run in a higher-prio thread to avoid issues with `async-io` getting\n    // confused by the low priority of the ESP IDF main task\n    // Also allocate a very large stack (for now) as `rs-matter` futures do occupy quite some space\n    let thread = std::thread::Builder::new()\n        .stack_size(85 * 1024)\n        .spawn(|| {\n            // Eagerly initialize `async-io` to minimize the risk of stack blowups later on\n            init_async_io()?;\n\n            run()\n        })\n        .unwrap();\n\n    thread.join().unwrap()\n}\n\n#[inline(never)]\n#[cold]\nfn run() -\u003e Result\u003c(), anyhow::Error\u003e {\n    let result = block_on(matter());\n\n    if let Err(e) = \u0026result {\n        error!(\"Matter aborted execution with error: {e:?}\");\n    }\n    {\n        info!(\"Matter finished execution successfully\");\n    }\n\n    result\n}\n\nasync fn matter() -\u003e Result\u003c(), anyhow::Error\u003e {\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(EspWifiMatterStack::init_default(\n            \u0026TEST_DEV_DET,\n            TEST_DEV_COMM,\n            \u0026TEST_DEV_ATT,\n        ));\n\n    // Take some generic ESP-IDF stuff we'll need later\n    let sysloop = EspSystemEventLoop::take()?;\n    let timers = EspTaskTimerService::new()?;\n    let nvs = EspDefaultNvsPartition::take()?;\n    let peripherals = Peripherals::take()?;\n\n    // Our \"light\" on-off handler.\n    // Can be anything implementing `Handler` or `AsyncHandler`\n    let on_off = OnOffHandler::new(Dataver::new_rand(stack.matter().rand())).adapt();\n\n    // Chain our endpoint clusters with the\n    // (root) Endpoint 0 system clusters in the final handler\n    let handler = EmptyHandler\n        // Our on-off cluster, on Endpoint 1\n        .chain(\n            EpClMatcher::new(Some(LIGHT_ENDPOINT_ID), Some(OnOffHandler::CLUSTER.id)),\n            Async(\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(DescHandler::CLUSTER.id)),\n            Async(desc::DescHandler::new(Dataver::new_rand(stack.matter().rand())).adapt()),\n        );\n\n    // Run the Matter stack with our handler\n    // Using `pin!` is completely optional, but saves some memory due to `rustc`\n    // not being very intelligent w.r.t. stack usage in async functions\n    //\n    // NOTE: When testing initially, use the `DummyKVBlobStore` to make sure device\n    // commissioning works fine with your controller. Once you confirm, you can enable\n    // the `EspKvBlobStore` to persist the Matter state in NVS.\n    // let store = stack.create_shared_store(esp_idf_matter::persist::EspKvBlobStore::new_default(nvs.clone())?);\n    let store = stack.create_shared_store(rs_matter_stack::persist::DummyKvBlobStore);\n    let mut matter = pin!(stack.run(\n        // The Matter stack needs the Wifi/BLE modem peripheral\n        EspMatterWifi::new_with_builtin_mdns(peripherals.modem, sysloop, timers, nvs, stack),\n        // The Matter stack needs a persister to store its state\n        \u0026store,\n        // Our `AsyncHandler` + `AsyncMetadata` impl\n        (NODE, handler),\n        // No user future to run\n        (),\n    ));\n\n    // Just for demoing purposes:\n    //\n    // Run a sample loop that simulates state changes triggered by the HAL\n    // Changes will be properly communicated to the Matter controllers\n    // (i.e. Google Home, Alexa) and other Matter devices thanks to subscriptions\n    let mut device = pin!(async {\n        loop {\n            // Simulate user toggling the light with a physical switch every 5 seconds\n            Timer::after(Duration::from_secs(5)).await;\n\n            // Toggle\n            on_off.0.set(!on_off.0.get());\n\n            // Let the Matter stack know that we have changed\n            // the state of our Light device\n            stack.notify_changed();\n\n            info!(\"Light toggled\");\n        }\n    });\n\n    // Schedule the Matter run \u0026 the device loop together\n    select(\u0026mut matter, \u0026mut device).coalesce().await?;\n\n    Ok(())\n}\n\n/// The Matter stack is allocated statically to avoid\n/// program stack blowups.\n/// It is also a mandatory requirement when the `WifiBle` stack variation is used.\nstatic MATTER_STACK: StaticCell\u003cEspWifiMatterStack\u003c()\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        EspWifiMatterStack::\u003c()\u003e::root_endpoint(),\n        Endpoint {\n            id: LIGHT_ENDPOINT_ID,\n            device_types: devices!(DEV_TYPE_ON_OFF_LIGHT),\n            clusters: clusters!(DescHandler::CLUSTER, OnOffHandler::CLUSTER),\n        },\n    ],\n};\n```\n\n## Future\n\n* Thread networking (for ESP32H2 and ESP32C6)\n* Device Attestation data support using secure flash storage\n* Setting system time via Matter\n* Matter OTA support based on the ESP-IDF OTA API\n\n## Build Prerequisites\n\nFollow the [Prerequisites](https://github.com/esp-rs/esp-idf-template#prerequisites) section in the `esp-idf-template` crate.\n\n## All examples\n\nThe examples could be built and flashed conveniently with [`cargo-espflash`](https://github.com/esp-rs/espflash/). To run e.g. `light` on an e.g. ESP32-C3:\n(Swap the Rust target and example name with the target corresponding for your ESP32 MCU and with the example you would like to build)\n\nwith `cargo-espflash`:\n```sh\n$ MCU=esp32c3 cargo espflash flash --target riscv32imc-esp-espidf --example light --features examples --monitor\n```\n\n| MCU | \"--target\" |\n| --- | ------ |\n| esp32c2 | riscv32imc-esp-espidf |\n| esp32c3| riscv32imc-esp-espidf |\n| esp32c6| riscv32imac-esp-espidf |\n| esp32h2 | riscv32imac-esp-espidf |\n| esp32p4 | riscv32imafc-esp-espidf |\n| esp32 | xtensa-esp32-espidf |\n| esp32s2 | xtensa-esp32s2-espidf |\n| esp32s3 | xtensa-esp32s3-espidf |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsysgrok%2Fesp-idf-matter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsysgrok%2Fesp-idf-matter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsysgrok%2Fesp-idf-matter/lists"}