Skip to content
Draft
4 changes: 2 additions & 2 deletions rs-matter-embassy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ rs-matter = { git = "https://github.com/sysgrok/rs-matter", branch = "next" }
#rs-matter = { path = "../../rs-matter/rs-matter" }
rs-matter-stack = { git = "https://github.com/ivmarkov/rs-matter-stack.git", branch = "next" }
#rs-matter-stack = { path = "../../rs-matter-stack" }
openthread = { git = "https://github.com/sysgrok/openthread.git" }
#openthread = { version = "0.1", path = "../../../openthread/openthread" }
# Fork with set_link_mode method: https://github.com/esp-rs/openthread/pull/50
openthread = { git = "https://github.com/lexfrei/openthread", branch = "feat/add-set-link-mode" }
nrf-sdc = { git = "https://github.com/alexmoon/nrf-sdc.git", rev = "11d5c3c3653af73b511133c2f8231f33eb0696f4" }
nrf-mpsl = { git = "https://github.com/alexmoon/nrf-sdc.git", rev = "11d5c3c3653af73b511133c2f8231f33eb0696f4" }

Expand Down
38 changes: 18 additions & 20 deletions rs-matter-embassy/src/ot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,16 @@ impl NetCtl for OtNetCtl<'_> {
select(self.0.wait_changed(), Timer::after(Duration::from_secs(1))).await;
}

// Enable rx_on_when_idle AFTER Thread attach so device can receive
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Must be called after the device has joined the network, not before".

Why is that? Do we know the root cause reason?

// unsolicited messages (CASE sessions, etc.). Must be called after
// the device has joined the network, not before.
// Parameters: rx_on_when_idle=true, device_type=false (MTD), network_data=false
if let Err(e) = self.0.set_link_mode(true, false, false) {
warn!("Failed to set link mode: {:?}", e);
} else {
info!("Link mode set: rx_on_when_idle=true");
}

Ok(())
}
}
Expand Down Expand Up @@ -421,6 +431,14 @@ impl<'d> OtMdns<'d> {

/// Run the `OtMdns` instance by listening to the mDNS services and registering them with the SRP server
pub async fn run(&self, matter: &Matter<'_>) -> Result<(), OtError> {
// On first iteration only: clean up any stale SRP records from previous runs.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have concerns with this.
To my understanding, you can't just forget your own SRP record because then you can't re-register yourself with the same SRP server anymore, under the same fqdn.

You really need to first remove your registration from the SRP server, and then re-register. Also, and if I remember correctly, when you claim a fqdn, you receive some sort of key from the SRP server, and the key and the fqdn are all saved (or should be saved) in the persistent storage of OpenThread => the persistent storage of rs-matter, so that they survive device reboot.

But perhaps I'm missing something, if you could elaborate?

// Using immediate removal (true) avoids blocking on slow/unreachable
// SRP servers which would consume the Matter Fail-Safe timer.
if !self.ot.srp_is_empty()? {
let _ = self.ot.srp_remove_all(true);
info!("SRP startup cleanup: removed stale records");
}

loop {
// TODO: Not very efficient to remove and re-add everything

Expand All @@ -443,26 +461,6 @@ impl<'d> OtMdns<'d> {
"Unreachable"
);

// If the device was restarted, this call will make sure that
// the SRP records are removed from the SRP server
let _ = self.ot.srp_set_conf(&SrpConf {
host_name: hostname.as_str(),
..Default::default()
});

let _ = self.ot.srp_remove_all(false);

// TODO: Something is still not quite right with the SRP
// We seem to get stuck here
while !self.ot.srp_is_empty()? {
debug!("Waiting for SRP records to be removed...");
select(
Timer::after(Duration::from_secs(1)),
self.ot.srp_wait_changed(),
)
.await;
}

self.ot.srp_set_conf(&SrpConf {
host_name: hostname.as_str(),
..Default::default()
Expand Down
53 changes: 51 additions & 2 deletions rs-matter-embassy/src/wireless/thread.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use core::pin::pin;

use embassy_futures::select::select3;
use embassy_futures::select::{select3, select4};
use embassy_time::{Duration, Timer};
use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};

use openthread::{OpenThread, Radio};
Expand Down Expand Up @@ -366,8 +367,51 @@ where
let mut persist = pin!(persister.run());
ot.enable_ipv6(true).map_err(to_matter_err)?;
ot.srp_autostart().map_err(to_matter_err)?;
info!("SRP autostart enabled");

// Enable rx_on_when_idle so device can receive unsolicited messages (CASE, etc.)
// Parameters: rx_on_when_idle=true, device_type=false (MTD), network_data=false
ot.set_link_mode(true, false, false)
.map_err(to_matter_err)?;

// SRP diagnostic task - logs status every 1 second for debugging
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having this diagnostics doesn't hurt, but if you could move to a separate async function - log_srp_state or such.

let ot_diag = ot.clone();
let mut srp_diag = pin!(async {
let mut tick = 0u32;
loop {
Timer::after(Duration::from_secs(1)).await;
tick += 1;

let server_addr = ot_diag.srp_server_addr().ok().flatten();

// Count services and their states
let mut total = 0u8;
let mut registered = 0u8;
let mut adding = 0u8;
let mut removing = 0u8;
let _ = ot_diag.srp_services(|svc| {
if let Some((_, state, _)) = svc {
total += 1;
match state {
openthread::SrpState::Registered => registered += 1,
openthread::SrpState::Adding | openthread::SrpState::ToAdd => adding += 1,
openthread::SrpState::Removing | openthread::SrpState::ToRemove => removing += 1,
_ => {}
}
}
});

if let Some(addr) = server_addr {
info!("SRP[{}s]: srv={}, reg={}/{}, add={}, rm={}", tick, addr, registered, total, adding, removing);
} else {
warn!("SRP[{}s]: NO SERVER, svc={}", tick, total);
}
}
#[allow(unreachable_code)]
Ok::<(), Error>(())
});

let result = select3(&mut main, &mut radio, &mut persist)
let result = select4(&mut main, &mut radio, &mut persist, &mut srp_diag)
.coalesce()
.await;

Expand Down Expand Up @@ -436,6 +480,11 @@ where
ot.enable_ipv6(true).map_err(to_matter_err)?;
ot.srp_autostart().map_err(to_matter_err)?;

// Enable rx_on_when_idle so device can receive unsolicited messages (CASE, etc.)
// Parameters: rx_on_when_idle=true, device_type=false (MTD), network_data=false
ot.set_link_mode(true, false, false)
.map_err(to_matter_err)?;

let result = select3(&mut main, &mut radio, &mut persist)
.coalesce()
.await;
Expand Down
Loading