Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove duplicate state from system clusters #197

Merged
merged 1 commit into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions examples/onoff_light/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
* limitations under the License.
*/

use core::borrow::Borrow;
use core::pin::pin;
use std::net::UdpSocket;

Expand Down Expand Up @@ -108,7 +107,7 @@ fn run() -> Result<(), Error> {

let mut mdns = pin!(run_mdns(&matter));

let on_off = cluster_on_off::OnOffCluster::new(*matter.borrow());
let on_off = cluster_on_off::OnOffCluster::new(Dataver::new_rand(matter.rand()));

let subscriptions = Subscriptions::<3>::new();

Expand Down Expand Up @@ -153,7 +152,7 @@ fn run() -> Result<(), Error> {
Some((
CommissioningData {
// TODO: Hard-coded for now
verifier: VerifierData::new_with_pw(123456, *matter.borrow()),
verifier: VerifierData::new_with_pw(123456, matter.rand()),
discriminator: 250,
},
Default::default(),
Expand Down Expand Up @@ -196,11 +195,11 @@ fn dm_handler<'a>(
) -> impl Metadata + NonBlockingHandler + 'a {
(
NODE,
root_endpoint::eth_handler(0, matter)
root_endpoint::eth_handler(0, matter.rand())
.chain(
1,
descriptor::ID,
descriptor::DescriptorCluster::new(*matter.borrow()),
descriptor::DescriptorCluster::new(Dataver::new_rand(matter.rand())),
)
.chain(1, cluster_on_off::ID, on_off),
)
Expand Down
93 changes: 28 additions & 65 deletions rs-matter/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* limitations under the License.
*/

use core::{borrow::Borrow, cell::RefCell};
use core::cell::RefCell;

use embassy_sync::blocking_mutex::raw::NoopRawMutex;

Expand All @@ -27,7 +27,7 @@ use crate::{
},
error::*,
fabric::FabricMgr,
mdns::{Mdns, MdnsService},
mdns::MdnsService,
pairing::{print_pairing_code_and_qr, DiscoveryCapabilities},
secure_channel::{pake::PaseMgr, spake2p::VerifierData},
transport::{
Expand Down Expand Up @@ -57,11 +57,11 @@ pub struct Matter<'a> {
pub(crate) failsafe: RefCell<FailSafe>,
pub transport_mgr: TransportMgr<'a>, // Public for tests
persist_notification: Notification<NoopRawMutex>,
pub(crate) epoch: Epoch,
pub(crate) rand: Rand,
epoch: Epoch,
rand: Rand,
dev_det: &'a BasicInfoConfig<'a>,
dev_att: &'a dyn DevAttDataFetcher,
pub(crate) port: u16,
port: u16,
}

impl<'a> Matter<'a> {
Expand Down Expand Up @@ -125,6 +125,14 @@ impl<'a> Matter<'a> {
self.port
}

pub fn rand(&self) -> Rand {
self.rand
}

pub fn epoch(&self) -> Epoch {
self.epoch
}

/// A utility method to replace the initial mDNS implementation with another one.
///
/// Useful in particular with `MdnsService::Provided`, where the user would still like
Expand Down Expand Up @@ -172,6 +180,21 @@ impl<'a> Matter<'a> {
self.acl_mgr.borrow().is_changed() || self.fabric_mgr.borrow().is_changed()
}

/// Return `true` if there is at least one commissioned fabric
//
// TODO:
// The implementation of this method needs to change in future,
// because the current implementation does not really track whether
// `CommissioningComplete` had been actually received for the fabric.
//
// The fabric is created once we receive `AddNoc`, but that's just
// not enough. The fabric should NOT be considered commissioned until
// after we receive `CommissioningComplete` on behalf of a Case session
// for the fabric in question.
pub fn is_commissioned(&self) -> bool {
self.fabric_mgr.borrow().used_count() > 0
}

fn start_comissioning(
&self,
dev_comm: CommissioningData,
Expand Down Expand Up @@ -261,63 +284,3 @@ impl<'a> Matter<'a> {
self.persist_notification.wait().await
}
}

impl<'a> Borrow<RefCell<FabricMgr>> for Matter<'a> {
fn borrow(&self) -> &RefCell<FabricMgr> {
&self.fabric_mgr
}
}

impl<'a> Borrow<RefCell<AclMgr>> for Matter<'a> {
fn borrow(&self) -> &RefCell<AclMgr> {
&self.acl_mgr
}
}

impl<'a> Borrow<RefCell<PaseMgr>> for Matter<'a> {
fn borrow(&self) -> &RefCell<PaseMgr> {
&self.pase_mgr
}
}

impl<'a> Borrow<RefCell<FailSafe>> for Matter<'a> {
fn borrow(&self) -> &RefCell<FailSafe> {
&self.failsafe
}
}

impl<'a> Borrow<TransportMgr<'a>> for Matter<'a> {
fn borrow(&self) -> &TransportMgr<'a> {
&self.transport_mgr
}
}

impl<'a> Borrow<BasicInfoConfig<'a>> for Matter<'a> {
fn borrow(&self) -> &BasicInfoConfig<'a> {
self.dev_det
}
}

impl<'a> Borrow<dyn DevAttDataFetcher + 'a> for Matter<'a> {
fn borrow(&self) -> &(dyn DevAttDataFetcher + 'a) {
self.dev_att
}
}

impl<'a> Borrow<dyn Mdns + 'a> for Matter<'a> {
fn borrow(&self) -> &(dyn Mdns + 'a) {
&self.transport_mgr.mdns
}
}

impl<'a> Borrow<Epoch> for Matter<'a> {
fn borrow(&self) -> &Epoch {
&self.epoch
}
}

impl<'a> Borrow<Rand> for Matter<'a> {
fn borrow(&self) -> &Rand {
&self.rand
}
}
80 changes: 47 additions & 33 deletions rs-matter/src/data_model/cluster_basic_information.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@

use core::cell::RefCell;

use super::objects::*;
use crate::{
attribute_enum,
error::{Error, ErrorCode},
utils::rand::Rand,
};
use heapless::String;
use rs_matter_macros::idl_import;

use strum::FromRepr;

use crate::attribute_enum;
use crate::error::{Error, ErrorCode};
use crate::transport::exchange::Exchange;

use super::objects::*;

idl_import!(clusters = ["BasicInformation"]);

pub use basic_information::ID;
Expand Down Expand Up @@ -136,48 +136,57 @@ pub const CLUSTER: Cluster<'static> = Cluster {
};

#[derive(Clone)]
pub struct BasicInfoCluster<'a> {
pub struct BasicInfoCluster {
data_ver: Dataver,
cfg: &'a BasicInfoConfig<'a>,
node_label: RefCell<String<32>>, // Max node-label as per the spec
node_label: RefCell<heapless::String<32>>, // Max node-label as per the spec
}

impl<'a> BasicInfoCluster<'a> {
pub fn new(cfg: &'a BasicInfoConfig<'a>, rand: Rand) -> Self {
let node_label = RefCell::new("".try_into().unwrap());
impl BasicInfoCluster {
pub const fn new(data_ver: Dataver) -> Self {
Self {
data_ver: Dataver::new(rand),
cfg,
node_label,
data_ver,
node_label: RefCell::new(heapless::String::new()),
}
}

pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> {
pub fn read(
&self,
exchange: &Exchange,
attr: &AttrDetails,
encoder: AttrDataEncoder,
) -> Result<(), Error> {
if let Some(writer) = encoder.with_dataver(self.data_ver.get())? {
if attr.is_system() {
CLUSTER.read(attr.attr_id, writer)
} else {
let cfg = exchange.matter().dev_det();

match attr.attr_id.try_into()? {
Attributes::DMRevision(codec) => codec.encode(writer, 1),
Attributes::VendorName(codec) => codec.encode(writer, self.cfg.vendor_name),
Attributes::VendorId(codec) => codec.encode(writer, self.cfg.vid),
Attributes::ProductName(codec) => codec.encode(writer, self.cfg.product_name),
Attributes::ProductId(codec) => codec.encode(writer, self.cfg.pid),
Attributes::VendorName(codec) => codec.encode(writer, cfg.vendor_name),
Attributes::VendorId(codec) => codec.encode(writer, cfg.vid),
Attributes::ProductName(codec) => codec.encode(writer, cfg.product_name),
Attributes::ProductId(codec) => codec.encode(writer, cfg.pid),
Attributes::NodeLabel(codec) => {
codec.encode(writer, self.node_label.borrow().as_str())
}
Attributes::HwVer(codec) => codec.encode(writer, self.cfg.hw_ver),
Attributes::SwVer(codec) => codec.encode(writer, self.cfg.sw_ver),
Attributes::SwVerString(codec) => codec.encode(writer, self.cfg.sw_ver_str),
Attributes::SerialNo(codec) => codec.encode(writer, self.cfg.serial_no),
Attributes::HwVer(codec) => codec.encode(writer, cfg.hw_ver),
Attributes::SwVer(codec) => codec.encode(writer, cfg.sw_ver),
Attributes::SwVerString(codec) => codec.encode(writer, cfg.sw_ver_str),
Attributes::SerialNo(codec) => codec.encode(writer, cfg.serial_no),
}
}
} else {
Ok(())
}
}

pub fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> {
pub fn write(
&self,
_exchange: &Exchange,
attr: &AttrDetails,
data: AttrData,
) -> Result<(), Error> {
let data = data.with_dataver(self.data_ver.get())?;

match attr.attr_id.try_into()? {
Expand All @@ -197,19 +206,24 @@ impl<'a> BasicInfoCluster<'a> {
}
}

impl<'a> Handler for BasicInfoCluster<'a> {
fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> {
BasicInfoCluster::read(self, attr, encoder)
impl Handler for BasicInfoCluster {
fn read(
&self,
exchange: &Exchange,
attr: &AttrDetails,
encoder: AttrDataEncoder,
) -> Result<(), Error> {
BasicInfoCluster::read(self, exchange, attr, encoder)
}

fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> {
BasicInfoCluster::write(self, attr, data)
fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> {
BasicInfoCluster::write(self, exchange, attr, data)
}
}

impl<'a> NonBlockingHandler for BasicInfoCluster<'a> {}
impl NonBlockingHandler for BasicInfoCluster {}

impl<'a> ChangeNotifier<()> for BasicInfoCluster<'a> {
impl ChangeNotifier<()> for BasicInfoCluster {
fn consume_change(&mut self) -> Option<()> {
self.data_ver.consume_change(())
}
Expand Down
45 changes: 32 additions & 13 deletions rs-matter/src/data_model/cluster_on_off.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@

use core::cell::Cell;

use super::objects::*;
use crate::{
attribute_enum, cmd_enter, command_enum, error::Error, tlv::TLVElement,
transport::exchange::Exchange, utils::rand::Rand,
};
use log::info;

use rs_matter_macros::idl_import;

use strum::{EnumDiscriminants, FromRepr};

use crate::error::Error;
use crate::tlv::TLVElement;
use crate::transport::exchange::Exchange;
use crate::{attribute_enum, cmd_enter, command_enum};

use super::objects::*;

idl_import!(clusters = ["OnOff"]);

pub use on_off::ID;
Expand Down Expand Up @@ -68,9 +72,9 @@ pub struct OnOffCluster {
}

impl OnOffCluster {
pub fn new(rand: Rand) -> Self {
pub const fn new(data_ver: Dataver) -> Self {
Self {
data_ver: Dataver::new(rand),
data_ver,
on: Cell::new(false),
}
}
Expand All @@ -86,7 +90,12 @@ impl OnOffCluster {
}
}

pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> {
pub fn read(
&self,
_exchange: &Exchange,
attr: &AttrDetails,
encoder: AttrDataEncoder,
) -> Result<(), Error> {
if let Some(writer) = encoder.with_dataver(self.data_ver.get())? {
if attr.is_system() {
CLUSTER.read(attr.attr_id, writer)
Expand All @@ -100,7 +109,12 @@ impl OnOffCluster {
}
}

pub fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> {
pub fn write(
&self,
_exchange: &Exchange,
attr: &AttrDetails,
data: AttrData,
) -> Result<(), Error> {
let data = data.with_dataver(self.data_ver.get())?;

match attr.attr_id.try_into()? {
Expand Down Expand Up @@ -144,12 +158,17 @@ impl OnOffCluster {
}

impl Handler for OnOffCluster {
fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> {
OnOffCluster::read(self, attr, encoder)
fn read(
&self,
exchange: &Exchange,
attr: &AttrDetails,
encoder: AttrDataEncoder,
) -> Result<(), Error> {
OnOffCluster::read(self, exchange, attr, encoder)
}

fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> {
OnOffCluster::write(self, attr, data)
fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> {
OnOffCluster::write(self, exchange, attr, data)
}

fn invoke(
Expand Down
Loading
Loading