project-chip / rs-matter Goto Github PK
View Code? Open in Web Editor NEWRust implementation of the Matter protocol. Status: Experimental
License: Apache License 2.0
Rust implementation of the Matter protocol. Status: Experimental
License: Apache License 2.0
Nightly Rust on Debian 10
nightly-x86_64-unknown-linux-gnu (overridden by '/home/chung/repos/matter-rs/rust-toolchain.toml')
rustc 1.70.0-nightly (478cbb42b 2023-03-28)
❯ RUST_BACKTRACE=1 cargo run --example onoff_light
Finished dev [optimized + debuginfo] target(s) in 0.09s
Running `target/debug/examples/onoff_light`
[2023-07-10T04:54:36Z INFO onoff_light] Matter memory: mDNS=320, Matter=12080, Transport=39736
[2023-07-10T04:54:36Z INFO onoff_light] Will use network interface enp3s0 with for mDNS
[2023-07-10T04:54:36Z INFO onoff_light] Persisting from/to /tmp/matter-iot
[2023-07-10T04:54:36Z INFO matter::transport::core] Starting Matter transport
[2023-07-10T04:54:36Z INFO matter::pairing::code] Pairing Code:
[2023-07-10T04:54:36Z INFO matter::pairing::qr] QR Code:
[2023-07-10T04:54:36Z INFO matter::pairing::qr]
[2023-07-10T04:54:36Z INFO matter::transport::core] Comissioning started
[2023-07-10T04:54:36Z INFO matter::transport::udp::smol_udp] Listening on [::]:5540
Error: Error::StdIoError {
0: matter::error::Error::new
at ./matter/src/error.rs:93:24
1: <matter::error::Error as core::convert::From<std::io::error::Error>>::from
at ./matter/src/error.rs:141:9
2: <core::result::Result<T,F> as core::ops::try_trait::FromResidual<core::result::Result<core::convert::Infallible,E>>>::from_residual
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/core/src/result.rs:2067:27
3: matter::transport::udp::smol_udp::UdpListener::new::{{closure}}
at ./matter/src/transport/udp.rs:39:25
4: matter::mdns::builtin::MdnsRunner::run_udp::{{closure}}
at ./matter/src/mdns/builtin.rs:124:76
5: onoff_light::run::{{closure}}
at ./matter/../examples/onoff_light/src/main.rs:223:63
6: <core::pin::Pin<P> as core::future::future::Future>::poll
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/core/src/future/future.rs:125:9
7: <&mut F as core::future::future::Future>::poll
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/core/src/future/future.rs:113:9
8: <embassy_futures::select::Select<A,B> as core::future::future::Future>::poll
at /home/chung/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-futures-0.1.0/src/select.rs:55:33
9: onoff_light::run::{{closure}}
at ./matter/../examples/onoff_light/src/main.rs:225:71
10: <core::pin::Pin<P> as core::future::future::Future>::poll
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/core/src/future/future.rs:125:9
11: <&mut F as core::future::future::Future>::poll
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/core/src/future/future.rs:113:9
12: async_io::driver::block_on
at /home/chung/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-1.12.0/src/driver.rs:146:33
13: onoff_light::run
at ./matter/../examples/onoff_light/src/main.rs:228:5
14: core::ops::function::FnOnce::call_once
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/core/src/ops/function.rs:250:5
15: std::sys_common::backtrace::__rust_begin_short_backtrace
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/std/src/sys_common/backtrace.rs:134:18
16: std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/std/src/thread/mod.rs:525:17
17: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/core/src/panic/unwind_safe.rs:271:9
18: std::panicking::try::do_call
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/std/src/panicking.rs:485:40
19: std::panicking::try
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/std/src/panicking.rs:449:19
20: std::panic::catch_unwind
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/std/src/panic.rs:140:14
21: std::thread::Builder::spawn_unchecked_::{{closure}}
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/std/src/thread/mod.rs:524:30
22: core::ops::function::FnOnce::call_once{{vtable.shim}}
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/core/src/ops/function.rs:250:5
23: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/alloc/src/boxed.rs:1988:9
24: <alloc::boxed::Box<F,A> as core::ops::function::FnOnce<Args>>::call_once
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/alloc/src/boxed.rs:1988:9
25: std::sys::unix::thread::Thread::new::thread_start
at /rustc/478cbb42b730ba4739351b72ce2aa928e78e2f81/library/std/src/sys/unix/thread.rs:108:17
26: start_thread
27: __clone
}
I have the not so comfy feeling, that the tests covering rs-matter
are just not enough, and so we are prone to regressions as we develop it over time. (Guilty as charged here, btw.)
Unit tests are one thing, but they can only go so far.
Also, the higher up you climb the stack, the more difficult it becomes to create and maintain such ones.
Though - I must say - the way I've influenced the existing semi-unit-tests/semi-e2e-tests that originally tested the Interaction/Data Layer is that they are currently more of an e2e test suite - as they are exercising aspects of the transport layer too - than what they were originally - tests bound to the Data layer only. So we might evolve this "framework" too, but writing the test cases themselves is super-boring, ergo, I'm looking at reusing someone else's test cases.
Regardless, and without digressing any further, the question:
@kedars, @andreilitvin: Are there / is there an e2e test framework in the C++ SDK that we can somehow extract and re-use in the context of rs-matter
?
I'm imagining - roughly speaking - a bunch of automation tests - likely in the form of shell or Python scripts exercising the chip-tool
command line and executed against an up-and-running version of the C++ SDK (which we should be able to replace with an up-and-running rs-matter
stack).
So, does such an animal exist, in there? Can you point me to it?
I'm unable to use the project as a dependency on an ESP32 based project.
Please see a minimal reproduction at https://github.com/nevi-me/esp32-c3-matter-minimal. The summary is that some of the dependencies don't yet support the esp-idf framework. The esp-rs
folks are aware of some of them, as there are forks at https://github.com/esp-rs-compat.
Turns out the domain
library is versatile enough so that we can completely get rid of on-stack buffers like this one.
Ongoing work in this branch of edge-mdns
.
If successful (which seems more and more likely now that I can serialize even TXT records without extra buffers), I'll merge back bits and pieces from this new implementation into rs-matter
.
Where I think our current naming convention (primarily for types and module names, but perhaps not only) is inconsistent:
sdm
(System Data Model): ok, but then we have un-abbreviated system_model
and interaction_model
ethernet_nw_diagnostics
: why abbreviate network
to nw
when diagnostics
and ethernet
are not abbreviatednw_commissioning
- dittoEndptId
- we have saved only 2 characters compared to - say - EndpointId
, and the word endpoint
is not abbreviated anywhere else, nor is ClusterId
abbreviated which is only 1 char shorterethernet_nw_diagnostics
, but then EthNwDiagCluster
. If we abbreviate the cluster name, perhaps we should abbreviate the module name as well, i.e. eth_nw_diag
?The list can continue, and probably the first step would be to identify a set of names that need to be refactor-renamed, as well as a justification why.
Ideally, we should be consistent in our abbreviations, even if we won't overdo it by building a glossary (but consulting the internet and then using common abbreviations, like here and here should be mandatory).
I don't think we need to waterfallish-ly come up with a long list of identifiers for renaming and only then open a giant PR for that. Yet we should probably follow at least these two rules:
Environment
Chip: ESP32-C3-MINI-1
Hardware: ESP32-C3-DevKitM-1
Platform: esp-idf (Rust std)
Problem
I likely have something misconfigured on my network causing IPv6 broadcasts to yield a surprising "Host is unreachable" error, however the more important issue is that the way the master future is structured in my example (and onoff_light) causes the entire Matter runtime to effectively shutdown and not automatically restart.
An abridged version of the log shows the issue:
I (7607) rs_matter::transport::core: Comissioning started
I (7617) rs_matter::transport::core: Creating queue for 1 exchanges
I (7617) rs_matter::transport::core: Creating 8 handlers
I (7627) rs_matter::transport::core: Handlers size: 9992
I (7637) rs_matter::transport::core: Transport: waiting for incoming packets
I (7647) rs_matter::transport::udp::async_io: Listening on [::]:5353
I (7647) rs_matter::transport::udp::async_io: Joined IPV6 multicast ff02::fb/2
I (7657) rs_matter::transport::udp::async_io: Joined IP multicast 224.0.0.251/192.168.86.32
I (7667) rs_matter::mdns::builtin: Broadcasting mDNS entry to 224.0.0.251:5353
I (7687) rs_matter::mdns::builtin: Broadcasting mDNS entry to ff02::fb:5353
W (7697) rs_matter::transport::udp::async_io: Error on the network: Os { code: 118, kind: HostUnreachable, message: "Host is unreachable" }
Error: Error::Network
The last line in particular appears to be coming from the master future in the onoff light example: https://github.com/project-chip/rs-matter/blob/main/examples/onoff_light/src/main.rs#L165
This is "fixed" by just disabling IPv6 for me, but I do think this highlights some bigger issues with the error handling robustness inside the runtime. In particular I'd expect that the IPv4 and IPv6 behaviour be separated into separate futures that can error out independently and that one reaching a terminal state wouldn't negatively impact the other. Further I think some measure of error handling policy is appropriate (Host is unreachable seems like it should probably be retryable for example). I could take a crack at a patch but I do worry based on the current state of the code that it might be a bit intrusive. Any guidance from the maintainers would be greatly appreciated before getting started!
Thanks again for this awesome project, it's renewed my interest big time in IoT :)
I got the onoff_light example working on my ESP32-C3-DevKitM-1 (after some tweaking to remove IPv6 support, see #100), but I'm having a couple of issues getting the device to appear and be controllable from Google Home.
First, trying to scan the QR code doesn't work and immediately produces an error as soon as I move my phone camera nearby to the QR code (see [1] below). If I switch to manually entering the pairing code things progress and I see a lot of log spamming from the device (which all looks successful generally and nothing appears to timeout).
Second, after seemingly trying to pair with the new device and bring it into Google Home I'm presented with [2] and I can't do anything to try again or proceed, only back out.
Full logs from boot-up attached here: https://gist.github.com/jasta/ed826fed780f9cc6109499b3fbe4f852
Is this expected? If no, anything I can try to do to debug and figure out what's wrong? I was able to successfully add a device using the main C++ matter repository and the all-clusters-app example and it seemingly worked well even to control the device. This was however a few months ago with a beta of Google Home.
EDIT: Apologies I just realized the screenshots are in Spanish. [1] is saying that it's not a matter QR code, and [2] is saying that the device isn't certified for use with Matter.
I hope this message finds you well. I am reaching out to kindly request the upload of the matter-rs packages to crates.io in order to facilitate their usage in our projects.
We have been eagerly following the development of matter-rs
and are impressed by its features and potential benefits for our projects. However, we have encountered difficulty in accessing the crates through crates.io, which is the primary repository for Rust packages.
To ensure seamless integration and compatibility within our projects, we kindly request that you consider publishing the matter-rs
packages to crates.io. This will enable us and other members of the Rust community to easily include and utilize this valuable resource in our development workflows.
We understand the effort and dedication required to maintain and distribute crates, and we truly appreciate your contribution to the Rust ecosystem. By making the matter-rs
packages available on crates.io, you would greatly enhance their accessibility and encourage wider adoption among developers.
Thank you for your time and consideration. We look forward to your positive response and eagerly anticipate the availability of the matter-rs
packages on crates.io.
After implementing PR #7 the pairing of the onoff_light can be started from Apple Home using the QR code.
It prompts the user that the device is uncertified. After confirming the dialog, the process continues.
Ultimately the onboarding fails, indicating that the accessory could not be paired.
In the logs there is no error, or an indication as to what went wrong:
The following older sections of the code (pre 2024) need a lot more documentation:
handlers
, objects
, encoding
module and otherstransport
layer, and possibly packet parsing / creationI suggest we just add it over time. I can do IM layer
and Sessions code
as in the meantime my code contributions there prevail over the original code, and there, the complexity is a bit bigger.
I'll start opening PRs with this.
Hello there,
I have a suggestion regarding the print_pairing_code_and_qr()
function. Currently, it accepts comm_data: &CommissioningData
as an argument. However, according to section 5.1 of the Matter-1.0-Core-Specification, both MPC and QR Code require a passcode.
The CommissioningData
has either VerifierOption::Password
or VerifierOption::Verifier
. In my understanding, passing VerifierOption::Verifier
instead of VerifierOption::Password
as an argument to print_pairing_code_and_qr()
will result in a runtime error.
To avoid this issue, I recommend passing VerifierOption::Password
as the argument to print_pairing_code_and_qr()
instead.
The existing two examples (onoff_light
and the upcoming onoff_light_bt
) have a lot of code duplication which will only grow if more examples are coming:
common/dev_att.rs
fileinclude_bytes!
rather than encoding the certificates in static Rust slicesOn the other hand, examples are supposed to be straightforward, even if that means a bit of a code duplication. So beyond moving the device attestation to a common file (which is non-controversial), we have to see what else makes sense to unify.
Examples also tend to be very verbose currently, and that's because rs-matter
is more of a toolkit rather than a ready-to-use solution.
Perhaps we need something like rs-matter-stack
in future as a sibling crate to the existing ones? For one, it tends to produce much smaller examples, as that crate is more oppinionated.
During pairing with Apple Home a panic was triggered in crypto_mbedtls.rs
.
This happened only once and I was unable to reproduce the issue so far. Will update this issue if it happens again.
[2023-01-15T10:52:02Z INFO matter::data_model::sdm::noc] Handling Command CSRRequest
[2023-01-15T10:52:02Z INFO matter::data_model::sdm::noc] Received CSR Nonce:OctetStr([52, 226, 46, 191, 82, 255, 246, 250, 115, 248, 188, 209, 33, 137, 211, 219, 31, 19, 195, 59, 234, 232, 71, 18, 40, 161, 131, 213, 218, 57, 218, 134])
thread 'main' panicked at 'attempt to subtract with overflow', src/crypto/crypto_mbedtls.rs:290:19
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Branch : no_std
Platform : Darwin arm64 (M1 Mac Book Pro)
When trying to run the example on M1 Mac I get the following error.
I might have time to investigate this later in the meantime I'm leaving this here:
matter-rs % bash -c "RUST_BACKTRACE=1 cargo run --example onoff_light"
warning: Patch `polling v2.2.0 (https://github.com/esp-rs-compat/polling#0a016089)` was not used in the crate graph.
Patch `smol v1.2.5 (https://github.com/esp-rs-compat/smol#15918c3c)` was not used in the crate graph.
Patch `socket2 v0.4.5 (https://github.com/esp-rs-compat/socket2#afeb7231)` was not used in the crate graph.
Check that the patched package version and available features are compatible
with the dependency requirements. If the patch has a different version from
what is locked in the Cargo.lock file, run `cargo update` to use the new
version. This may also occur with an optional dependency that is not enabled.
Finished dev [optimized + debuginfo] target(s) in 0.26s
Running `target/debug/examples/onoff_light`
[2023-06-30T07:59:59Z INFO onoff_light] Matter memory: mDNS=320, Matter=12080, Transport=39736
[2023-06-30T07:59:59Z INFO onoff_light] Will use network interface en0 with 10.5.221.91/fe80::1ca2:f0c3:35b1:2a5d for mDNS
[2023-06-30T07:59:59Z INFO onoff_light] Persisting from/to /var/folders/zf/jdpvrr2n04v_pgcx1_hjkn300000gn/T/matter-iot
[2023-06-30T07:59:59Z INFO matter::transport::core] Starting Matter transport
[2023-06-30T07:59:59Z INFO matter::pairing::code] Pairing Code: 0087-6800-071
[2023-06-30T07:59:59Z INFO matter::pairing::qr] QR Code: MT:Y.K90Q1212Z6Q66D33P084L90Z.I332SQ43I15T0
[2023-06-30T07:59:59Z INFO matter::pairing::qr]
█████████████████████████████████████
█████████████████████████████████████
████ ▄▄▄▄▄ █▀██ █▀▀▄ █ ▄█ ▄▄▄▄▄ ████
████ █ █ █ ▀█▀▄▄█▄▀▄ ▄▄█ █ █ ████
████ █▄▄▄█ ██▄ █ ██ ▄ ▀▀▀█ █▄▄▄█ ████
████▄▄▄▄▄▄▄█ █▄█ █ ▀ █ █ █▄▄▄▄▄▄▄████
████▄▀▀▀▀▀▄█▄▀█ █▀██ ▀ ██▄ ▀▀ ▄ ▀████
████▀█ ▀▀▄ ▄▄▀▄▄ ▄▄▄█▀█▄██▄ ▄▀▀▄████
████▀ ▀ █▄▄▀▄▀▀█ ▄█▄ ▀ ▀█ ██ ▀▀████
████ █ █▀▄█ ▄▀▀██▀█▀█ ▀▄ ▀ ██ ▄████
████▀▄▄█▄ ▄ ▀ ▀ ▄▀▀█▄▀█▀▄▄▀▄▄▀ ▀ ████
████ ▄▀█▄█▄ ▄█▀▄█▀█▄█▄▄▄█▄█ ▄ ▀████
████▄█▄██▄▄█▀▀ █ ▄█▀█▄ ▄▄▄ ▄▀▀▄████
████ ▄▄▄▄▄ ██▀█ ▄█▀▀▀▀ ▀ █▄█ ▄▄ ▄████
████ █ █ ██ ▀█▄▄ █▄▀██▄▄▄ ▄▄ ▀▄████
████ █▄▄▄█ ██ ▀▀ ▄█▄▀▄▀█▀▄▀ ▀ ▄█████
████▄▄▄▄▄▄▄█▄█████▄▄██▄▄█▄██▄█▄▄█████
█████████████████████████████████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
[2023-06-30T07:59:59Z INFO matter::transport::core] Comissioning started
[2023-06-30T07:59:59Z INFO matter::transport::udp::smol_udp] Listening on [::]:5540
Error: Error::StdIoError {
0: std::backtrace::Backtrace::create
1: matter::error::Error::new
at ./matter/src/error.rs:93:24
2: <matter::error::Error as core::convert::From<std::io::error::Error>>::from
at ./matter/src/error.rs:141:9
3: <core::result::Result<T,F> as core::ops::try_trait::FromResidual<core::result::Result<core::convert::Infallible,E>>>::from_residual
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/core/src/result.rs:2002:27
4: matter::transport::udp::smol_udp::UdpListener::new::{{closure}}
at ./matter/src/transport/udp.rs:39:25
5: matter::mdns::builtin::MdnsRunner::run_udp::{{closure}}
at ./matter/src/mdns/builtin.rs:124:76
6: onoff_light::run::{{closure}}
at ./matter/../examples/onoff_light/src/main.rs:223:63
7: <core::pin::Pin<P> as core::future::future::Future>::poll
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/core/src/future/future.rs:125:9
8: <&mut F as core::future::future::Future>::poll
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/core/src/future/future.rs:113:9
9: <embassy_futures::select::Select<A,B> as core::future::future::Future>::poll
at /Users/nikolasvonlonski/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embassy-futures-0.1.0/src/select.rs:55:33
10: onoff_light::run::{{closure}}
at ./matter/../examples/onoff_light/src/main.rs:225:71
11: <core::pin::Pin<P> as core::future::future::Future>::poll
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/core/src/future/future.rs:125:9
12: <&mut F as core::future::future::Future>::poll
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/core/src/future/future.rs:113:9
13: async_io::driver::block_on
at /Users/nikolasvonlonski/.cargo/registry/src/index.crates.io-6f17d22bba15001f/async-io-1.12.0/src/driver.rs:146:33
14: onoff_light::run
at ./matter/../examples/onoff_light/src/main.rs:228:5
15: core::ops::function::FnOnce::call_once
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/core/src/ops/function.rs:250:5
16: std::sys_common::backtrace::__rust_begin_short_backtrace
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/std/src/sys_common/backtrace.rs:134:18
17: std::thread::Builder::spawn_unchecked_::{{closure}}::{{closure}}
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/std/src/thread/mod.rs:526:17
18: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/core/src/panic/unwind_safe.rs:271:9
19: std::panicking::try::do_call
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/std/src/panicking.rs:485:40
20: std::panicking::try
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/std/src/panicking.rs:449:19
21: std::panic::catch_unwind
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/std/src/panic.rs:140:14
22: std::thread::Builder::spawn_unchecked_::{{closure}}
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/std/src/thread/mod.rs:525:30
23: core::ops::function::FnOnce::call_once{{vtable.shim}}
at /private/tmp/rust-20230613-7622-103lepv/rustc-1.70.0-src/library/core/src/ops/function.rs:250:5
24: std::sys::unix::thread::Thread::new::thread_start
25: __pthread_joiner_wake
}
I'm trying to commission a test device utilizing this crate with a SmartThings Hub. It's currently failing to establish CASE, and I've tracked it down to the verification of the initiator ICAC sent by the controller to the device.
This is what I could find in the spec about validating the Sigma3 message:
The responder SHALL verify that the NOC in TBEData3.responderNOC and the ICAC in TBEData3.responderICAC fulfill the following constraints:
a. The Fabric ID SHALL match the Fabric ID matched during processing of the Destination
Identifier after receiving Sigma1.
b. If an ICAC is present, and it contains a Fabric ID in its subject, then it SHALL match the Fab
ricID in the NOC leaf certificate.
c. The certificate chain SHALL chain back to the Trusted Root CA Certificate TrustedRCAC whose
public key was matched during processing of the Destination Identifier after receiving Sig
ma1.
d. All the elements in the certificate chain SHALL respect the Matter Certificate DN Encoding
Rules, including range checks for identifiers such as Fabric ID and Node ID.
The only validation specified for ICAC is that the fabric ID matches that of the NOC leaf certificate, which appears to be done here:
I've verified that that is occurring with log statements. However, just below that, it is failing to add the cert to the verifier. From adding my own logs, I've determined that it is failing here:
rs-matter/rs-matter/src/cert/mod.rs
Line 600 in 320d1ec
The ICAC has no subject key ID extension, so the function returns an error. Given that the ST Hub is Matter certified I suspect that something is overly strict with this certificate verification. However, this is out of my realm of expertise.
I also logged the ICAC following the parsing from TLV in case that's helpful:
Cert {
serial_no: OctetStr([67, 38, 73, 198, 26, 31, 20, 101, 57, 46, 16, 143, 77, 160, 128, 161]),
sign_algo: 1,
issuer: DistNames {
dn: [(20, Uint(15512483513290480383))]
},
not_before: 718486395,
not_after: 874187555,
subject: DistNames {
dn: [(19, Uint(14440658877384716286))]
},
pubkey_algo: 1,
ec_curve_id: 1,
pubkey: OctetStr([4, 88, 188, 13, 87, 50, 3, 213, 248, 182, 12, 240, 164, 220, 127, 150, 65, 81, 244, 125, 24, 48, 203, 83, 111, 133, 175, 182, 10, 40, 80, 147, 28, 39, 121, 183, 61, 159, 178, 231, 133, 75, 189, 143, 136, 191, 254, 115, 228, 186, 129, 56, 137, 213, 177, 13, 46, 97, 202, 95, 41, 5, 16, 24, 228]),
extensions: Extensions {
basic_const: Some(BasicConstraints { is_ca: true, path: Some(0) }),
key_usage: None,
ext_key_usage: None,
subj_key_id: None,
auth_key_id: Some(OctetStr([243, 119, 107, 152, 3, 212, 205, 76, 85, 38, 158, 240, 27, 213, 11, 235, 33, 21, 38, 5])),
future_extensions: None
},
signature: OctetStr([70, 43, 150, 195, 194, 170, 43, 125, 91, 213, 210, 221, 175, 131, 131, 85, 22, 247, 213, 18, 101, 189, 30, 134, 20, 226, 217, 145, 41, 225, 181, 150, 28, 200, 52, 237, 218, 195, 144, 209, 205, 73, 88, 114, 139, 216, 85, 170, 63, 238, 164, 69, 35, 69, 39, 87, 211, 234, 57, 98, 19, 43, 13, 0])
}
We need to update all copyright headers as they currently say "Copyright 2020 - 2022..." and 2022 is in the past.
Is the CSA alliance having any prescriptions here? If not:
@andreilitvin mentioned the C++ SDK has a policy to put newer copyright only in the files they newly add (or change?) BUT I do not understand this policy at all.
Copyright headers of all files - old or new always need to be up to date. Always. Not a lawyer, but pretty sure about that. Otherwise it would look as if the copyright of the old files had expired, which is just not the case.
Two options I can think of:
What to do with the beginning year? Also two options:
Copying the part of #181 which is still unresolved here, to keep the discussion open:
Apple Matter is a bit weird. Putting aside the fact that we are commissioned into two fabrics, the other weird thing that happens is that once we are commissioned in the second fabric, they are communicating with us on behalf of TWO different IP addresses, which - however - do represent the same node+fabric ID?!
fe80::8d7:cf23:8b0b:f715%2
- in fact this guy has two different nodes, one on fabric 1, and another on fabric 2 - see our session dump belowfe80::416:93dd:216a:d50a%2
- this guy has the only one node on fabric 1 (or so we know), but its node on Fabric 1 is the same as the node of the previous IP!And now the real weird part: we receive a subscription request from IP Address 2 and this all goes well.
But when the time comes to report on that subscription in some seconds / minutes and initiate a new exchange, it just so happens that we select an existing session for "IP Address 1" instead, because we are just looking for a session matching the fabric index (=1) and the node ID. And since the first address also has created sessions to us on behalf of fabric 1, we just happen to pick a session for IP Address 1, even if the subscription came from IP Address 2.
... and get "Invalid Subscription" from the other peer.
Now, if we pick a session based on fabric index + peer node ID + remote address, then we select a session with "IP Address 2" (the address from where the subscription came) and all is well!
So @kedars what do you think is going on? Shall I just also keep the IP address in the subscription data and do a match by that address too? This works (confirmed) but sounds a bit weird. Am I missing something in the spec?
Session dump:
Sessions for IP Address 1:
=============================================
(Skip this block, it contains non-CASE sessions, not interesting):
Session: fb_idx: None, peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(1088638830675445622), local_nodeid: 0, local: 0, remote: 0, msg_ctr: 9017568, mode: PlainText, ts: 1717612457.779132481s
Session: fb_idx: None, peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(0), local_nodeid: 0, local: 1, remote: 8566, msg_ctr: 44517232, mode: Pase(NotExpected), ts: 1717612462.458154527s
Session: fb_idx: None, peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(9297024357880017542), local_nodeid: 0, local: 0, remote: 0, msg_ctr: 87475376, mode: PlainText, ts: 1717612462.78951294s
Session: fb_idx: None, peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(17849542785653146437), local_nodeid: 0, local: 0, remote: 0, msg_ctr: 35224863, mode: PlainText, ts: 1717612493.671745767s
Session: fb_idx: None, peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(1088638830675445622), local_nodeid: 0, local: 0, remote: 0, msg_ctr: 9017568, mode: PlainText, ts: 1717612457.779132481s
Session: fb_idx: None, peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(0), local_nodeid: 0, local: 1, remote: 8566, msg_ctr: 44517232, mode: Pase(NotExpected), ts: 1717612462.458154527s
Session: fb_idx: None, peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(9297024357880017542), local_nodeid: 0, local: 0, remote: 0, msg_ctr: 87475376, mode: PlainText, ts: 1717612462.78951294s
Session: fb_idx: None, peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(17849542785653146437), local_nodeid: 0, local: 0, remote: 0, msg_ctr: 35224863, mode: PlainText, ts: 1717612493.671745767s
!!! This block is interesting:
Session: fb_idx: Some(1), peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(864992019), local_nodeid: 1121512030, local: 2, remote: 8567, msg_ctr: 198121502, mode: Case(CaseDetails { fab_idx: 1, cat_ids: [0, 0, 0] }), ts: 1717612496.261807843s
Session: fb_idx: Some(2), peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(3725013030), local_nodeid: 4012158658, local: 3, remote: 8568, msg_ctr: 254531801, mode: Case(CaseDetails { fab_idx: 2, cat_ids: [0, 0, 0] }), ts: 1717612494.724025958s
Session: fb_idx: Some(1), peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(864992019), local_nodeid: 1121512030, local: 2, remote: 8567, msg_ctr: 198121502, mode: Case(CaseDetails { fab_idx: 1, cat_ids: [0, 0, 0] }), ts: 1717612500.816538095s
Session: fb_idx: Some(2), peer: [fe80::8d7:cf23:8b0b:f715%2]:51398, peer_nodeid: Some(3725013030), local_nodeid: 4012158658, local: 3, remote: 8568, msg_ctr: 254531801, mode: Case(CaseDetails { fab_idx: 2, cat_ids: [0, 0, 0] }), ts: 1717612494.724025958s
Sessions for IP Address 2:
=============================================
(Skip this block, it contains non-CASE sessions, not interesting):
Session: fb_idx: None, peer: [fe80::416:93dd:216a:d50a%2]:65218, peer_nodeid: Some(1162526195568380034), local_nodeid: 0, local: 0, remote: 0, msg_ctr: 84020839, mode: PlainText, ts: 1717612496.321803477s
Session: fb_idx: None, peer: [fe80::416:93dd:216a:d50a%2]:65218, peer_nodeid: Some(1162526195568380034), local_nodeid: 0, local: 0, remote: 0, msg_ctr: 84020839, mode: PlainText, ts: 1717612496.321803477s
!!! This block is interesting: see - fb_idx = 1 and peer_nodeid = 864992019 which is also present for Address 1?!
Session: fb_idx: Some(1), peer: [fe80::416:93dd:216a:d50a%2]:65218, peer_nodeid: Some(864992019), local_nodeid: 1121512030, local: 4, remote: 48265, msg_ctr: 226861159, mode: Case(CaseDetails { fab_idx: 1, cat_ids: [0, 0, 0] }), ts: 1717612500.815073586s
Session: fb_idx: Some(1), peer: [fe80::416:93dd:216a:d50a%2]:65218, peer_nodeid: Some(864992019), local_nodeid: 1121512030, local: 4, remote: 48265, msg_ctr: 226861159, mode: Case(CaseDetails { fab_idx: 1, cat_ids: [0, 0, 0] }), ts: 1717612500.815073586s
Follow-up on #66
Handle error scenarios gracefully
Since the merge of #147 , we now do have subscriptions and we do report on these.
However, the current implementation is a bit suboptimal, in that it always reports everything, regardless whether any of the attributes reported by the subscription are actually changed.
I also believe that the existing ChangeNotifier
idea, which is somewhat implemented throughout the code (but unfinished), might not have a future, as I don't see it helping in anyway to solve the problem:
write
or invoke
command from a remote peer, we are anyway notified via the AsyncHandler
callbacks.I think something more fruitful would be if the notification is traversing all clusters it reports on, and trying to detect (possibly by comparing against a preserved set of datavers, or a simpler -hash-based derivation of multiple datavers) if there are changes or not.
When an interaction arrives at the device, the TLV contents are logged, but it's not easy to get the cluster path or attribute being read. The general commissioning cluster handlers have some code for invoke commands, but it'd make it easier to debug from log captures if the log line included information about the cluster being queried in a ReadRequest or other requests, like in #102
Hello matter-rs,
sorry for creating a non-issue. Please simply close it if that is not interesting for you.
I‘m one of the maintainers of matter.js (also project under project-chip orga) and we implement matter in JavaScript/typescript.
To support the open source community in developing with and for matter I also created a discord called „matter-integrators“ where I would like to invite you. There are already other open source projects like the tasmota matter implementations in and beside building a developer community it also started to be a good place to exchange opinions on matter specs and how to read/interpret it ;-).
Thank you and maybe see you there ;-)
Ingo
Hi,
The instructions for how to build rs-matter for esp-idf were removed in pull request #129 citing that support was upstreamed. Unfortunately it is now unclear from looking at the repository whether using matter-rs on an ESP32 is supported, and if so what networking stack is supported (wifi, threads... etc).
Some clarification with minimal build instructions on how to build rs-matter for ESP-IDF would be amazing.
(@kedars We should probably open the "Discussions" functionality in the GH project, and then make one item there, "Meetings". Or at least this is what the esp-rs
folks practice.)
CC: @jasta @MabezDev @jessebraham
UnsupportedAttribute
(to be confirmed)chiptool
the Matter C++ device what exactly it returns for UniqueId
- empty strong or notUniqueId
returns a default values, we should treat it as a special case, as we do nowOnOffCluster
sample implementation is part of the rs-matter
library, while it should be provided as part of the example, to make it clear that users should provide their own oneIt would be useful for us to have code coverage in CI, especially for the crypto backends.
Depending on what service we use, this might require some integrating the repo to an external service, e.g. coveralls.
I can work on the Github Actions part and figure out how coverage will work for mutually exclusive targets, then I can leave some instructions for how a repo admin can enable CI on a service.
Here a Result is returned, whereas an error case is not handled. Since no error case is handled, I'd like to suggest returning Self
instead of a result, which would remove a lot of question mark operators within the library. This is not a minor refactor, therefore I'd like to post it as an issue first. Would love to hear what you think!
Turns out the reason is we don't (yet) support the RevokeComm
command on the admin cluster.
My next
branch has an impl that fixes the issue. To be merged soon, hopefully.
On M1 on the sequential branch running the onoff_light example and commissioning with Apple Home the device is unable to be commissioned.
Using chip-tool it works.
I'm able to commission my own custom devices based on the main repo (project-chip/connectedhomeip) just fine.
The only Error I can see in the log is the following :
[2023-07-12T11:15:48Z ERROR matter::acl] ACL Disallow for subjects [1921388213, ] fab idx 1
[2023-07-12T11:15:48Z ERROR matter::acl] ACLS: []
Any pointers in the right direction would be appreciated.
Here is the full log :
error.log
Add an error: Box<dyn std::error::Error>
member to the Error
enum here. Then include the original error message (and possibly its backtrace, if any) in the Debug
and Display
impl for the matter-rs Error
enum.
Just like the backtrace
member, it should be enabled only when both std
and backtrace
features are enabled, as it would be bringing non-trivial cost to the unhappy path.
Yet very useful for proper diagnostics of errors originating outside of matter-rs
itself.
Hi,
Thanks for picking up the work to create a Rust version of the Matter implementation. Not an easy endeavour.
I've done a bit of experimenting with your "old" repository and am looking forward to see how this work develops.
My main objective is to replace the current HomeKit bridge that was developed with (https://github.com/ewilken/hap-rs) with a Matter equivalent.
I have an Apple eco-system with Somfy smart devices and use the bridge to connect the two worlds.
If needed, I may be able to help test your code with Apple Home.
Kind regards,
Marcel
PS.
I'll do a PR that implements a bunch of Clippy suggestions. That should help quiet the compilation. 😄
reproduction:
expected: successful pairing
outcome: The Alexa App says: "Something gone wrong, an unexpected error occurred, please try again later" (Translated)
the important lines could be
[2023-10-03T15:07:59Z ERROR rs_matter::secure_channel::case] Certificate Chain doesn't match: Invalid:
[2023-10-03T15:07:59Z ERROR rs_matter::tlv::parser] Invalid value found: 0 self TLVListIterator { buf: [1, 0, 0, 0, 0, 0, 2, 0], current: 8 } size 1
I am new to matter and do not know anything about it.
The readme.md
mentions a chip-tool
, but there is no link to this tool.
At first, I thought that I installed this tool via espup, but that is not the case.
Through googling, I found this site and I guess that is the mentioned tool?
It would make sense to explain in the readme, how one can install the tool/where one can find it.
cargo generate esp-rs/esp-idf-template cargo
export MCU=esp32; export CARGO_TARGET_XTENSA_ESP32_ESPIDF_LINKER=ldproxy; export RUSTFLAGS="-C default-linker-libraries"; export WIFI_SSID=ssid;export WIFI_PASS=pass; cargo build --no-default-features --target xtensa-esp32-espidf -Zbuild-std=std,panic_abort
expected: successful build
outcome: error: failed to run custom build command for rs-matter v0.1.1
Error: environment variable not found
quite not sure which env variable is not set
To run this on an MCU it would be beneficial to support no_std
environments
I did a POC "from scratch" which is no_std
and no_alloc
here: https://github.com/bjoernQ/bare-matter (the code is very bad but might be an inspiration)
I guess making this completely no_alloc
will be hard but at least no_std
should be possible
I'm almost starting a zigbee project in rust. Will this project eventually have zigbee support? I'd like to not reinvent the wheel
I'm confused where I would add user code to actually do something with the on/off commands are received, am I missing something from the example code? It would seem that this is internally handled by OnOffCluster
with no ability for me to observe changes like we see with other clusters like MediaPlaybackCluster
. Perhaps we could include some simple print debugging or something when the user code would be expected to interact with a physical device to make this clearer for folks?
For a certain set of errors, specifically ErrorCode
s:
Crypto
TLSStack
BtpError
MdnsError
NoNetworkInterface
(we should actually rename this to NetworkError
)StdIoError
... we should:
backtrace
is enabled)Box<dyn Error>
(if feature std
is enabled, and also in future if feature alloc
is enabled given that ). Note that we currently preserve the original error only if BOTH std
and backtrace
are enabled, which is probably a bit too paranoiderror!
otherwise... to get extra context for debugging. Because these errors are:
The cost of preserving the original error should not be that high as we don't expect these errors to happen frequently, but unfortunately we can only due it in the presence of alloc
. Without alloc
, preserving the original errors means generics which will virally pollute all our APIs which is just plain impossible to handle.
We might even decide to model these errors in a different way from the rest. To be decided.
Hi, I'm implementing some of the clusters related to audio devices - level control, audio output, etc.
I will open a PR for them soon but there are some long-running commands that cause issues.
Specifically with level control - A lot of the commands contain optional transition time - they can take up X amount of seconds to complete. This obviously can't block the main thread as everything will time out and we need to issue a response right after we process it.
In order to have it run in the background, I've implemented a background thread for the level control cluster that will update some values and the main thread can update the data model from that whenever a command is issued. This has a problem currently - values are updated from this update-store only on writes, read interactions are not processed through the specific cluster implementations. So if we're slowly updating the level of a device from X to Y in the background, reads will not show this until an actual cluster commands is issued.
My question is, should I make this like a cluster trait for all clusters to implement on top of if needed? I assume some other clusters to be implemented in the future will also require handling of long running commands.
Any suggestions, or other ideas how to do this properly ?
This project looks really cool to me to build some easy and cross compatible lights with something like a raspberry pi or any other wireless connected device. I'd really like to use it with my custom built light, without needing to implement something specific to my current solution (I currently use HomeAssistant MQTT). It would be really nice to have dimmable, CCT, RGB and RGB-CCT lights supported by this SDK, that could make it really cool for home projects. (Also switches would be a great addition, but one thing at a time)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.