Skip to content

Commit 4bb0831

Browse files
committed
BasicInfo: Add ProductName/VendorName/NodeLabel
1 parent ce3bf6b commit 4bb0831

File tree

4 files changed

+86
-5
lines changed

4 files changed

+86
-5
lines changed

examples/onoff_light/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ fn run() -> Result<(), Error> {
7272
sw_ver_str: "1",
7373
serial_no: "aabbccdd",
7474
device_name: "OnOff Light",
75+
product_name: "Light123",
76+
vendor_name: "Vendor PQR",
7577
};
7678

7779
let (ipv4_addr, ipv6_addr, interface) = initialize_network()?;

rs-matter/src/data_model/cluster_basic_information.rs

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,15 @@
1515
* limitations under the License.
1616
*/
1717

18-
use core::convert::TryInto;
18+
use core::{cell::RefCell, convert::TryInto};
1919

2020
use super::objects::*;
21-
use crate::{attribute_enum, error::Error, utils::rand::Rand};
21+
use crate::{
22+
attribute_enum,
23+
error::{Error, ErrorCode},
24+
utils::rand::Rand,
25+
};
26+
use heapless::String;
2227
use strum::FromRepr;
2328

2429
pub const ID: u32 = 0x0028;
@@ -27,8 +32,11 @@ pub const ID: u32 = 0x0028;
2732
#[repr(u16)]
2833
pub enum Attributes {
2934
DMRevision(AttrType<u8>) = 0,
35+
VendorName(AttrUtfType) = 1,
3036
VendorId(AttrType<u16>) = 2,
37+
ProductName(AttrUtfType) = 3,
3138
ProductId(AttrType<u16>) = 4,
39+
NodeLabel(AttrUtfType) = 5,
3240
HwVer(AttrType<u16>) = 7,
3341
SwVer(AttrType<u32>) = 9,
3442
SwVerString(AttrUtfType) = 0xa,
@@ -39,8 +47,11 @@ attribute_enum!(Attributes);
3947

4048
pub enum AttributesDiscriminants {
4149
DMRevision = 0,
50+
VendorName = 1,
4251
VendorId = 2,
52+
ProductName = 3,
4353
ProductId = 4,
54+
NodeLabel = 5,
4455
HwVer = 7,
4556
SwVer = 9,
4657
SwVerString = 0xa,
@@ -57,6 +68,8 @@ pub struct BasicInfoConfig<'a> {
5768
pub serial_no: &'a str,
5869
/// Device name; up to 32 characters
5970
pub device_name: &'a str,
71+
pub vendor_name: &'a str,
72+
pub product_name: &'a str,
6073
}
6174

6275
pub const CLUSTER: Cluster<'static> = Cluster {
@@ -70,16 +83,31 @@ pub const CLUSTER: Cluster<'static> = Cluster {
7083
Access::RV,
7184
Quality::FIXED,
7285
),
86+
Attribute::new(
87+
AttributesDiscriminants::VendorName as u16,
88+
Access::RV,
89+
Quality::FIXED,
90+
),
7391
Attribute::new(
7492
AttributesDiscriminants::VendorId as u16,
7593
Access::RV,
7694
Quality::FIXED,
7795
),
96+
Attribute::new(
97+
AttributesDiscriminants::ProductName as u16,
98+
Access::RV,
99+
Quality::FIXED,
100+
),
78101
Attribute::new(
79102
AttributesDiscriminants::ProductId as u16,
80103
Access::RV,
81104
Quality::FIXED,
82105
),
106+
Attribute::new(
107+
AttributesDiscriminants::NodeLabel as u16,
108+
Access::RWVM,
109+
Quality::N,
110+
),
83111
Attribute::new(
84112
AttributesDiscriminants::HwVer as u16,
85113
Access::RV,
@@ -107,13 +135,16 @@ pub const CLUSTER: Cluster<'static> = Cluster {
107135
pub struct BasicInfoCluster<'a> {
108136
data_ver: Dataver,
109137
cfg: &'a BasicInfoConfig<'a>,
138+
node_label: RefCell<String<32>>, // Max node-label as per the spec
110139
}
111140

112141
impl<'a> BasicInfoCluster<'a> {
113142
pub fn new(cfg: &'a BasicInfoConfig<'a>, rand: Rand) -> Self {
143+
let node_label = RefCell::new(String::from(""));
114144
Self {
115145
data_ver: Dataver::new(rand),
116146
cfg,
147+
node_label,
117148
}
118149
}
119150

@@ -124,8 +155,13 @@ impl<'a> BasicInfoCluster<'a> {
124155
} else {
125156
match attr.attr_id.try_into()? {
126157
Attributes::DMRevision(codec) => codec.encode(writer, 1),
158+
Attributes::VendorName(codec) => codec.encode(writer, self.cfg.vendor_name),
127159
Attributes::VendorId(codec) => codec.encode(writer, self.cfg.vid),
160+
Attributes::ProductName(codec) => codec.encode(writer, self.cfg.product_name),
128161
Attributes::ProductId(codec) => codec.encode(writer, self.cfg.pid),
162+
Attributes::NodeLabel(codec) => {
163+
codec.encode(writer, self.node_label.borrow().as_str())
164+
}
129165
Attributes::HwVer(codec) => codec.encode(writer, self.cfg.hw_ver),
130166
Attributes::SwVer(codec) => codec.encode(writer, self.cfg.sw_ver),
131167
Attributes::SwVerString(codec) => codec.encode(writer, self.cfg.sw_ver_str),
@@ -136,12 +172,35 @@ impl<'a> BasicInfoCluster<'a> {
136172
Ok(())
137173
}
138174
}
175+
176+
pub fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> {
177+
let data = data.with_dataver(self.data_ver.get())?;
178+
179+
match attr.attr_id.try_into()? {
180+
Attributes::NodeLabel(codec) => {
181+
*self.node_label.borrow_mut() = String::from(
182+
codec
183+
.decode(data)
184+
.map_err(|_| Error::new(ErrorCode::InvalidAction))?,
185+
);
186+
}
187+
_ => return Err(Error::new(ErrorCode::InvalidAction)),
188+
}
189+
190+
self.data_ver.changed();
191+
192+
Ok(())
193+
}
139194
}
140195

141196
impl<'a> Handler for BasicInfoCluster<'a> {
142197
fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> {
143198
BasicInfoCluster::read(self, attr, encoder)
144199
}
200+
201+
fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> {
202+
BasicInfoCluster::write(self, attr, data)
203+
}
145204
}
146205

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

rs-matter/tests/common/im_engine.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ const BASIC_INFO: BasicInfoConfig<'static> = BasicInfoConfig {
7070
sw_ver_str: "13",
7171
serial_no: "aabbccdd",
7272
device_name: "Test Device",
73+
product_name: "TestProd",
74+
vendor_name: "TestVendor",
7375
};
7476

7577
struct DummyDevAtt;

rs-matter/tests/data_model/long_reads.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,36 @@ fn wildcard_read_resp(part: u8) -> Vec<AttrResp<'static>> {
6969
basic_info::AttributesDiscriminants::DMRevision,
7070
dont_care.clone()
7171
),
72+
attr_data!(
73+
0,
74+
40,
75+
basic_info::AttributesDiscriminants::VendorName,
76+
dont_care.clone()
77+
),
7278
attr_data!(
7379
0,
7480
40,
7581
basic_info::AttributesDiscriminants::VendorId,
7682
dont_care.clone()
7783
),
84+
attr_data!(
85+
0,
86+
40,
87+
basic_info::AttributesDiscriminants::ProductName,
88+
dont_care.clone()
89+
),
7890
attr_data!(
7991
0,
8092
40,
8193
basic_info::AttributesDiscriminants::ProductId,
8294
dont_care.clone()
8395
),
96+
attr_data!(
97+
0,
98+
40,
99+
basic_info::AttributesDiscriminants::NodeLabel,
100+
dont_care.clone()
101+
),
84102
attr_data!(
85103
0,
86104
40,
@@ -195,6 +213,9 @@ fn wildcard_read_resp(part: u8) -> Vec<AttrResp<'static>> {
195213
adm_comm::AttributesDiscriminants::AdminVendorId,
196214
dont_care.clone()
197215
),
216+
];
217+
218+
let part2 = vec![
198219
attr_data!(0, 62, GlobalElements::FeatureMap, dont_care.clone()),
199220
attr_data!(0, 62, GlobalElements::AttributeList, dont_care.clone()),
200221
attr_data!(
@@ -203,9 +224,6 @@ fn wildcard_read_resp(part: u8) -> Vec<AttrResp<'static>> {
203224
noc::AttributesDiscriminants::CurrentFabricIndex,
204225
dont_care.clone()
205226
),
206-
];
207-
208-
let part2 = vec![
209227
attr_data!(
210228
0,
211229
62,

0 commit comments

Comments
 (0)