-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
1,752 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ authors = ["ivmarkov <[email protected]>"] | |
edition = "2021" | ||
resolver = "2" | ||
categories = ["embedded", "hardware-support"] | ||
keywords = ["embedded", "svc", "idf", "esp-idf", "esp32"] | ||
keywords = ["matter", "embedded", "esp-idf", "esp32"] | ||
description = "Implementation of the embedded-svc traits for ESP-IDF (Espressif's IoT Development Framework)" | ||
repository = "https://github.com/ivmarkov/esp-idf-matter" | ||
license = "MIT OR Apache-2.0" | ||
|
@@ -15,15 +15,29 @@ build = "build.rs" | |
rust-version = "1.77" | ||
|
||
[patch.crates-io] | ||
embedded-svc = { git = "https://github.com/esp-rs/embedded-svc" } | ||
esp-idf-svc = { path = "../esp-idf-svc" } | ||
rs-matter = { path = "../rs-matter" } | ||
rs-matter = { path = "../rs-matter/rs-matter" } | ||
rs-matter-macros = { path = "../rs-matter/rs-matter-macros" } | ||
|
||
[features] | ||
default = ["std"] | ||
std = ["async-io", "rs-matter/std", "rs-matter/async-io"] | ||
|
||
[dependencies] | ||
log = { version = "0.4", default-features = false } | ||
esp-idf-svc = { version = "0.48", default-features = false, fatures = ["experimental"] } | ||
heapless = "0.8" | ||
enumset = { version = "1", default-features = false } | ||
strum = { version = "0.26", default-features = false, features = ["derive"] } | ||
embassy-futures = "0.1" | ||
embassy-sync = "0.5" | ||
esp-idf-svc = { version = "0.48", default-features = false, features = ["alloc", "embassy-sync", "experimental"] } | ||
rs-matter = { version = "0.1", default-features = false } | ||
rs-matter-macros = "0.1" | ||
async-io = { version = "2", optional = true, default-features = false } | ||
|
||
[build-dependencies] | ||
embuild = "0.31.3" | ||
|
||
[dev-dependencies] | ||
static_cell = "2.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
//! An example utilizing the `MatterStack<WifiBle>` struct. | ||
//! As the name suggests, this Matter stack assembly uses Wifi as the main transport, and BLE for commissioning. | ||
//! | ||
//! The example implements a fictitious Light device (an on-off cluster). | ||
|
||
fn main() -> Result<(), Error> { | ||
// Take the Matter stack (can be done only once), as we'll run it in this thread | ||
let stack = MATTER_STACK.take().unwrap(); | ||
|
||
// We need to pass the `modem` peripheral to the Matter stack, as it manages Bluetooth & Wifi by itself | ||
// | ||
// If we want to use Bluetooth for our own needs, that's possible post-commissioning, as long as the | ||
// coexist ESP IDF driver is loaded. We just need to then split the `modem` peripheral into BT and Wifi, | ||
// and only pass the Wifi half. | ||
let peripherals = Peripherals::take()?; | ||
|
||
// Matter needs (a clone of) the ESP IDF NVS service too | ||
let nvs = EspDefaultNvs::take()?; | ||
|
||
// Our "light" on-off cluster. Can be anything implementing `rs_matter::data_model::AsyncHandler` | ||
let on_off = cluster_on_off::OnOffCluster::new(stack.matter().borrow()); | ||
|
||
// Chain our endpoint clusters with the (root) Endpoint 0 system clusters in the final handler | ||
let handler = stack | ||
.root_handler() | ||
// Our on-off cluster, on Endpoint 1 | ||
.chain(LIGHT_ENDPOINT_ID, cluster_on_off::ID, on_off) | ||
// Each Endpoint needs a Descriptor cluster too | ||
// Just use the one that `rs-matter` provides out of the box | ||
.chain( | ||
LIGHT_ENDPOINT_ID, | ||
descriptor::ID, | ||
descriptor::DescriptorCluster::new(stack.matter().borrow()), | ||
); | ||
|
||
// Run the Matter stack with our handler | ||
let mut matter = pin!(async { stack.run(peripherals.modem, nvs, (NODE, handler)).await }); | ||
|
||
// Just for demoing purposes: | ||
// | ||
// Run a sample loop that simulates state changes triggered by the HAL | ||
// Changes will be properly communicated to the Matter controllers (i.e. Google Home, Alexa) | ||
// and other Matter devices thanks to subscriptions | ||
let mut device = pin!(async { | ||
loop { | ||
// Simulate user toggling the light with a physical switch every 5 seconds | ||
Timer::after(Duration::from_secs(5)).await; | ||
|
||
// Toggle | ||
on_off.set(!on_off.get()); | ||
|
||
// Let the Matter stack know that we have changed the state of our Lamp device | ||
stack.notify_changed(); | ||
|
||
info!("Lamp toggled"); | ||
} | ||
}); | ||
|
||
// Schedule both the Matter loop & the device loop together | ||
esp_idf_svc::hal::task::block_on(select(matter, device).coalesce())?; | ||
|
||
Ok(()) | ||
} | ||
|
||
/// The Matter stack is allocated statically to avoid program stack blowups | ||
static MATTER_STACK: StaticConstCell<MatterStack<WifiBle>> = | ||
StaticConstCell::new(MatterStack::new( | ||
&BasicInfoConfig { | ||
vid: 0xFFF1, | ||
pid: 0x8000, | ||
hw_ver: 2, | ||
sw_ver: 1, | ||
sw_ver_str: "1", | ||
serial_no: "aabbccdd", | ||
device_name: "MyLight", | ||
product_name: "ACME Light", | ||
vendor_name: "ACME", | ||
}, | ||
&dev_att::HardCodedDevAtt::new(), | ||
)); | ||
|
||
/// Endpoint 0 (the root endpoint) always runs the hidden Matter system clusters, so we pick ID=1 | ||
const LIGHT_ENDPOINT_ID: usize = 1; | ||
|
||
/// The Matter Light device Node | ||
const NODE: Node<'static> = Node { | ||
id: 0, | ||
endpoints: &[ | ||
Matter::<WifiBle>::root_metadata(), | ||
Endpoint { | ||
id: LIGHT_ENDPOINT_ID, | ||
device_type: DEV_TYPE_ON_OFF_LIGHT, | ||
clusters: &[descriptor::CLUSTER, cluster_on_off::CLUSTER], | ||
}, | ||
], | ||
}; |
Oops, something went wrong.