Skip to content

Commit

Permalink
Remove duplicate state from system clusters (#197)
Browse files Browse the repository at this point in the history
  • Loading branch information
ivmarkov authored Jun 27, 2024
1 parent 157152e commit 3054a32
Show file tree
Hide file tree
Showing 24 changed files with 983 additions and 832 deletions.
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

0 comments on commit 3054a32

Please sign in to comment.