1use anyhow::Result;
2
3use crate::{clusters, tlv};
4
5use super::Device;
6
7const ATTR_GENERATED_CMD_LIST: u32 = 0xFFF8;
9const ATTR_ACCEPTED_CMD_LIST: u32 = 0xFFF9;
10const ATTR_EVENT_LIST: u32 = 0xFFFA;
11const ATTR_ATTRIBUTE_LIST: u32 = 0xFFFB;
12const ATTR_FEATURE_MAP: u32 = 0xFFFC;
13const ATTR_CLUSTER_REVISION: u32 = 0xFFFD;
14
15impl Device {
16 pub(super) fn setup_default_attributes(&mut self) -> Result<()> {
17 use clusters::defs::*;
18
19
20 let mut buf = tlv::TlvBuffer::new();
21 buf.write_array(2)?;
22 buf.write_anon_struct()?;
23 buf.write_uint32(0, 0x0016)?; buf.write_uint16(1, 2)?; buf.write_struct_end()?;
26 buf.write_struct_end()?;
27 self.set_attribute_raw(
28 0,
29 CLUSTER_ID_DESCRIPTOR,
30 CLUSTER_DESCRIPTOR_ATTR_ID_DEVICETYPELIST,
31 &buf.data,
32 );
33
34 let mut buf = tlv::TlvBuffer::new();
35 buf.write_array(2)?;
36 buf.write_uint32_notag(CLUSTER_ID_DESCRIPTOR)?;
37 buf.write_uint32_notag(CLUSTER_ID_ACCESS_CONTROL)?;
38 buf.write_uint32_notag(CLUSTER_ID_BASIC_INFORMATION)?;
39 buf.write_uint32_notag(CLUSTER_ID_GENERAL_COMMISSIONING)?;
40 buf.write_uint32_notag(CLUSTER_ID_NETWORK_COMMISSIONING)?;
41 buf.write_uint32_notag(CLUSTER_ID_ADMINISTRATOR_COMMISSIONING)?;
42 buf.write_uint32_notag(CLUSTER_ID_OPERATIONAL_CREDENTIALS)?;
43 buf.write_struct_end()?;
44 self.set_attribute_raw(
45 0,
46 CLUSTER_ID_DESCRIPTOR,
47 CLUSTER_DESCRIPTOR_ATTR_ID_SERVERLIST,
48 &buf.data,
49 );
50
51 self.set_empty_array(0, CLUSTER_ID_DESCRIPTOR, CLUSTER_DESCRIPTOR_ATTR_ID_CLIENTLIST);
52
53 self.set_empty_array(0, CLUSTER_ID_DESCRIPTOR, CLUSTER_DESCRIPTOR_ATTR_ID_PARTSLIST);
54
55 self.set_cluster_globals(
56 0,
57 CLUSTER_ID_DESCRIPTOR,
58 3,
59 0,
60 &[
61 CLUSTER_DESCRIPTOR_ATTR_ID_DEVICETYPELIST,
62 CLUSTER_DESCRIPTOR_ATTR_ID_SERVERLIST,
63 CLUSTER_DESCRIPTOR_ATTR_ID_CLIENTLIST,
64 CLUSTER_DESCRIPTOR_ATTR_ID_PARTSLIST,
65 ],
66 &[],
67 &[],
68 )?;
69
70 let vendor_id = self.config.vendor_id;
71 let product_id = self.config.product_id;
72 self.set_attribute_u16(
73 0,
74 CLUSTER_ID_BASIC_INFORMATION,
75 CLUSTER_BASIC_INFORMATION_ATTR_ID_DATAMODELREVISION,
76 1,
77 );
78 let vendor_name = self.config.vendor_name.clone();
79 self.set_attribute_string(
80 0,
81 CLUSTER_ID_BASIC_INFORMATION,
82 CLUSTER_BASIC_INFORMATION_ATTR_ID_VENDORNAME,
83 &vendor_name,
84 );
85 self.set_attribute_u16(
86 0,
87 CLUSTER_ID_BASIC_INFORMATION,
88 CLUSTER_BASIC_INFORMATION_ATTR_ID_VENDORID,
89 vendor_id,
90 );
91 let product_name = self.config.product_name.clone();
92 self.set_attribute_string(
93 0,
94 CLUSTER_ID_BASIC_INFORMATION,
95 CLUSTER_BASIC_INFORMATION_ATTR_ID_PRODUCTNAME,
96 &product_name,
97 );
98 self.set_attribute_u16(
99 0,
100 CLUSTER_ID_BASIC_INFORMATION,
101 CLUSTER_BASIC_INFORMATION_ATTR_ID_PRODUCTID,
102 product_id,
103 );
104 let node_label = self.config.product_name.clone();
105 self.set_attribute_string(
106 0,
107 CLUSTER_ID_BASIC_INFORMATION,
108 CLUSTER_BASIC_INFORMATION_ATTR_ID_NODELABEL,
109 &node_label,
110 );
111 self.set_attribute_string(
112 0,
113 CLUSTER_ID_BASIC_INFORMATION,
114 CLUSTER_BASIC_INFORMATION_ATTR_ID_LOCATION,
115 "XX",
116 );
117 let hardware_version = self.config.hardware_version;
118 self.set_attribute_u16(
119 0,
120 CLUSTER_ID_BASIC_INFORMATION,
121 CLUSTER_BASIC_INFORMATION_ATTR_ID_HARDWAREVERSION,
122 hardware_version,
123 );
124 let hardware_version_string = format!("{}.0", hardware_version);
125 self.set_attribute_string(
126 0,
127 CLUSTER_ID_BASIC_INFORMATION,
128 CLUSTER_BASIC_INFORMATION_ATTR_ID_HARDWAREVERSIONSTRING,
129 &hardware_version_string,
130 );
131 let software_version = self.config.software_version;
132 self.set_attribute_u32(
133 0,
134 CLUSTER_ID_BASIC_INFORMATION,
135 CLUSTER_BASIC_INFORMATION_ATTR_ID_SOFTWAREVERSION,
136 software_version,
137 );
138 let software_version_string = software_version.to_string();
139 self.set_attribute_string(
140 0,
141 CLUSTER_ID_BASIC_INFORMATION,
142 CLUSTER_BASIC_INFORMATION_ATTR_ID_SOFTWAREVERSIONSTRING,
143 &software_version_string,
144 );
145 let serial_number = self.config.serial_number.clone();
146 self.set_attribute_string(
147 0,
148 CLUSTER_ID_BASIC_INFORMATION,
149 CLUSTER_BASIC_INFORMATION_ATTR_ID_SERIALNUMBER,
150 &serial_number,
151 );
152 self.set_attribute_bool(
153 0,
154 CLUSTER_ID_BASIC_INFORMATION,
155 CLUSTER_BASIC_INFORMATION_ATTR_ID_LOCALCONFIGDISABLED,
156 false,
157 );
158 self.set_attribute_bool(
159 0,
160 CLUSTER_ID_BASIC_INFORMATION,
161 CLUSTER_BASIC_INFORMATION_ATTR_ID_REACHABLE,
162 true,
163 );
164 let unique_id = self.config.unique_id.clone();
165 self.set_attribute_string(
166 0,
167 CLUSTER_ID_BASIC_INFORMATION,
168 CLUSTER_BASIC_INFORMATION_ATTR_ID_UNIQUEID,
169 &unique_id,
170 );
171
172 let mut buf = tlv::TlvBuffer::new();
173 buf.write_struct(2)?;
174 buf.write_uint16(0, 3)?; buf.write_uint16(1, 3)?; buf.write_struct_end()?;
177 self.set_attribute_raw(
178 0,
179 CLUSTER_ID_BASIC_INFORMATION,
180 CLUSTER_BASIC_INFORMATION_ATTR_ID_CAPABILITYMINIMA,
181 &buf.data,
182 );
183
184 self.set_attribute_u32(
185 0,
186 CLUSTER_ID_BASIC_INFORMATION,
187 CLUSTER_BASIC_INFORMATION_ATTR_ID_SPECIFICATIONVERSION,
188 0x01030000, );
190 self.set_attribute_u16(
191 0,
192 CLUSTER_ID_BASIC_INFORMATION,
193 CLUSTER_BASIC_INFORMATION_ATTR_ID_MAXPATHSPERINVOKE,
194 1,
195 );
196
197 self.set_cluster_globals(
198 0,
199 CLUSTER_ID_BASIC_INFORMATION,
200 4,
201 0,
202 &[
203 CLUSTER_BASIC_INFORMATION_ATTR_ID_DATAMODELREVISION,
204 CLUSTER_BASIC_INFORMATION_ATTR_ID_VENDORNAME,
205 CLUSTER_BASIC_INFORMATION_ATTR_ID_VENDORID,
206 CLUSTER_BASIC_INFORMATION_ATTR_ID_PRODUCTNAME,
207 CLUSTER_BASIC_INFORMATION_ATTR_ID_PRODUCTID,
208 CLUSTER_BASIC_INFORMATION_ATTR_ID_NODELABEL,
209 CLUSTER_BASIC_INFORMATION_ATTR_ID_LOCATION,
210 CLUSTER_BASIC_INFORMATION_ATTR_ID_HARDWAREVERSION,
211 CLUSTER_BASIC_INFORMATION_ATTR_ID_HARDWAREVERSIONSTRING,
212 CLUSTER_BASIC_INFORMATION_ATTR_ID_SOFTWAREVERSION,
213 CLUSTER_BASIC_INFORMATION_ATTR_ID_SOFTWAREVERSIONSTRING,
214 CLUSTER_BASIC_INFORMATION_ATTR_ID_SERIALNUMBER,
215 CLUSTER_BASIC_INFORMATION_ATTR_ID_LOCALCONFIGDISABLED,
216 CLUSTER_BASIC_INFORMATION_ATTR_ID_REACHABLE,
217 CLUSTER_BASIC_INFORMATION_ATTR_ID_UNIQUEID,
218 CLUSTER_BASIC_INFORMATION_ATTR_ID_CAPABILITYMINIMA,
219 CLUSTER_BASIC_INFORMATION_ATTR_ID_SPECIFICATIONVERSION,
220 CLUSTER_BASIC_INFORMATION_ATTR_ID_MAXPATHSPERINVOKE,
221 ],
222 &[],
223 &[],
224 )?;
225
226 self.set_attribute_u64(
227 0,
228 CLUSTER_ID_GENERAL_COMMISSIONING,
229 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_BREADCRUMB,
230 0,
231 );
232
233 let mut bci_tlv = tlv::TlvBuffer::new();
234 bci_tlv.write_struct(2)?;
235 bci_tlv.write_uint16(0, 100)?;
236 bci_tlv.write_uint16(1, 200)?;
237 bci_tlv.write_struct_end()?;
238 self.set_attribute_raw(
239 0,
240 CLUSTER_ID_GENERAL_COMMISSIONING,
241 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_BASICCOMMISSIONINGINFO,
242 &bci_tlv.data,
243 );
244
245 self.set_attribute_u8(
246 0,
247 CLUSTER_ID_GENERAL_COMMISSIONING,
248 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_REGULATORYCONFIG,
249 0,
250 );
251 self.set_attribute_u8(
252 0,
253 CLUSTER_ID_GENERAL_COMMISSIONING,
254 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_LOCATIONCAPABILITY,
255 0,
256 );
257 self.set_attribute_bool(
258 0,
259 CLUSTER_ID_GENERAL_COMMISSIONING,
260 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_SUPPORTSCONCURRENTCONNECTION,
261 true,
262 );
263 self.set_attribute_bool(
264 0,
265 CLUSTER_ID_GENERAL_COMMISSIONING,
266 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_ISCOMMISSIONINGWITHOUTPOWER,
267 false,
268 );
269
270 self.set_cluster_globals(
271 0,
272 CLUSTER_ID_GENERAL_COMMISSIONING,
273 1,
274 0,
275 &[
276 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_BREADCRUMB,
277 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_BASICCOMMISSIONINGINFO,
278 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_REGULATORYCONFIG,
279 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_LOCATIONCAPABILITY,
280 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_SUPPORTSCONCURRENTCONNECTION,
281 CLUSTER_GENERAL_COMMISSIONING_ATTR_ID_ISCOMMISSIONINGWITHOUTPOWER,
282 ],
283 &[
284 CLUSTER_GENERAL_COMMISSIONING_CMD_ID_ARMFAILSAFE,
285 CLUSTER_GENERAL_COMMISSIONING_CMD_ID_SETREGULATORYCONFIG,
286 CLUSTER_GENERAL_COMMISSIONING_CMD_ID_COMMISSIONINGCOMPLETE,
287 ],
288 &[
289 CLUSTER_GENERAL_COMMISSIONING_CMD_ID_ARMFAILSAFERESPONSE,
290 CLUSTER_GENERAL_COMMISSIONING_CMD_ID_SETREGULATORYCONFIGRESPONSE,
291 CLUSTER_GENERAL_COMMISSIONING_CMD_ID_COMMISSIONINGCOMPLETERESPONSE,
292 ],
293 )?;
294
295 self.set_attribute_u8(
296 0,
297 CLUSTER_ID_OPERATIONAL_CREDENTIALS,
298 CLUSTER_OPERATIONAL_CREDENTIALS_ATTR_ID_SUPPORTEDFABRICS,
299 8,
300 );
301 self.set_attribute_u8(
302 0,
303 CLUSTER_ID_OPERATIONAL_CREDENTIALS,
304 CLUSTER_OPERATIONAL_CREDENTIALS_ATTR_ID_COMMISSIONEDFABRICS,
305 1,
306 );
307 self.set_empty_array(
308 0,
309 CLUSTER_ID_OPERATIONAL_CREDENTIALS,
310 CLUSTER_OPERATIONAL_CREDENTIALS_ATTR_ID_FABRICS,
311 );
312
313 self.set_cluster_globals(
314 0,
315 CLUSTER_ID_OPERATIONAL_CREDENTIALS,
316 1,
317 0,
318 &[
319 CLUSTER_OPERATIONAL_CREDENTIALS_ATTR_ID_NOCS,
320 CLUSTER_OPERATIONAL_CREDENTIALS_ATTR_ID_FABRICS,
321 CLUSTER_OPERATIONAL_CREDENTIALS_ATTR_ID_SUPPORTEDFABRICS,
322 CLUSTER_OPERATIONAL_CREDENTIALS_ATTR_ID_COMMISSIONEDFABRICS,
323 CLUSTER_OPERATIONAL_CREDENTIALS_ATTR_ID_TRUSTEDROOTCERTIFICATES,
324 CLUSTER_OPERATIONAL_CREDENTIALS_ATTR_ID_CURRENTFABRICINDEX,
325 ],
326 &[
327 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_ATTESTATIONREQUEST,
328 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_CERTIFICATECHAINREQUEST,
329 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_CSRREQUEST,
330 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_ADDTRUSTEDROOTCERTIFICATE,
331 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_ADDNOC,
332 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_REMOVEFABRIC,
333 ],
334 &[
335 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_ATTESTATIONRESPONSE,
336 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_CERTIFICATECHAINRESPONSE,
337 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_CSRRESPONSE,
338 CLUSTER_OPERATIONAL_CREDENTIALS_CMD_ID_NOCRESPONSE,
339 ],
340 )?;
341
342
343 self.set_attribute_u8(
344 0,
345 CLUSTER_ID_NETWORK_COMMISSIONING,
346 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_MAXNETWORKS,
347 1,
348 );
349 self.set_empty_array(
350 0,
351 CLUSTER_ID_NETWORK_COMMISSIONING,
352 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_NETWORKS,
353 );
354 self.set_attribute_bool(
355 0,
356 CLUSTER_ID_NETWORK_COMMISSIONING,
357 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_INTERFACEENABLED,
358 true,
359 );
360 self.set_attribute_u8(
361 0,
362 CLUSTER_ID_NETWORK_COMMISSIONING,
363 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_CONNECTMAXTIMESECONDS,
364 120,
365 );
366 self.set_attribute_u8(
367 0,
368 CLUSTER_ID_NETWORK_COMMISSIONING,
369 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_LASTNETWORKINGSTATUS,
370 0,
371 );
372 self.set_attribute_u16(
373 0,
374 CLUSTER_ID_NETWORK_COMMISSIONING,
375 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_SUPPORTEDTHREADFEATURES,
376 0,
377 );
378
379 self.set_cluster_globals(
380 0,
381 CLUSTER_ID_NETWORK_COMMISSIONING,
382 1,
383 0x04, &[
385 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_MAXNETWORKS,
386 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_NETWORKS,
387 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_CONNECTMAXTIMESECONDS,
388 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_INTERFACEENABLED,
389 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_LASTNETWORKINGSTATUS,
390 CLUSTER_NETWORK_COMMISSIONING_ATTR_ID_SUPPORTEDTHREADFEATURES,
391 ],
392 &[],
393 &[],
394 )?;
395
396 self.set_empty_array(
397 0,
398 CLUSTER_ID_ACCESS_CONTROL,
399 CLUSTER_ACCESS_CONTROL_ATTR_ID_ACL,
400 );
401 self.set_attribute_u16(
402 0,
403 CLUSTER_ID_ACCESS_CONTROL,
404 CLUSTER_ACCESS_CONTROL_ATTR_ID_SUBJECTSPERACCESSCONTROLENTRY,
405 4,
406 );
407 self.set_attribute_u16(
408 0,
409 CLUSTER_ID_ACCESS_CONTROL,
410 CLUSTER_ACCESS_CONTROL_ATTR_ID_TARGETSPERACCESSCONTROLENTRY,
411 3,
412 );
413 self.set_attribute_u16(
414 0,
415 CLUSTER_ID_ACCESS_CONTROL,
416 CLUSTER_ACCESS_CONTROL_ATTR_ID_ACCESSCONTROLENTRIESPERFABRIC,
417 4,
418 );
419
420 self.set_cluster_globals(
421 0,
422 CLUSTER_ID_ACCESS_CONTROL,
423 2,
424 0,
425 &[
426 CLUSTER_ACCESS_CONTROL_ATTR_ID_ACL,
427 CLUSTER_ACCESS_CONTROL_ATTR_ID_SUBJECTSPERACCESSCONTROLENTRY,
428 CLUSTER_ACCESS_CONTROL_ATTR_ID_TARGETSPERACCESSCONTROLENTRY,
429 CLUSTER_ACCESS_CONTROL_ATTR_ID_ACCESSCONTROLENTRIESPERFABRIC,
430 ],
431 &[],
432 &[],
433 )?;
434
435 self.set_attribute_u8(
436 0,
437 CLUSTER_ID_ADMINISTRATOR_COMMISSIONING,
438 CLUSTER_ADMINISTRATOR_COMMISSIONING_ATTR_ID_WINDOWSTATUS,
439 0, );
441 self.set_attribute_u8(
442 0,
443 CLUSTER_ID_ADMINISTRATOR_COMMISSIONING,
444 CLUSTER_ADMINISTRATOR_COMMISSIONING_ATTR_ID_ADMINFABRICINDEX,
445 0,
446 );
447 self.set_attribute_u16(
448 0,
449 CLUSTER_ID_ADMINISTRATOR_COMMISSIONING,
450 CLUSTER_ADMINISTRATOR_COMMISSIONING_ATTR_ID_ADMINVENDORID,
451 0,
452 );
453
454 self.set_cluster_globals(
455 0,
456 CLUSTER_ID_ADMINISTRATOR_COMMISSIONING,
457 1,
458 0,
459 &[
460 CLUSTER_ADMINISTRATOR_COMMISSIONING_ATTR_ID_WINDOWSTATUS,
461 CLUSTER_ADMINISTRATOR_COMMISSIONING_ATTR_ID_ADMINFABRICINDEX,
462 CLUSTER_ADMINISTRATOR_COMMISSIONING_ATTR_ID_ADMINVENDORID,
463 ],
464 &[
465 CLUSTER_ADMINISTRATOR_COMMISSIONING_CMD_ID_OPENCOMMISSIONINGWINDOW,
466 CLUSTER_ADMINISTRATOR_COMMISSIONING_CMD_ID_OPENBASICCOMMISSIONINGWINDOW,
467 CLUSTER_ADMINISTRATOR_COMMISSIONING_CMD_ID_REVOKECOMMISSIONING,
468 ],
469 &[],
470 )?;
471
472 self.set_attribute_u8(0, 0x60, 1, 3u8);
474
475 Ok(())
476 }
477
478 pub fn set_empty_array(&mut self, endpoint: u16, cluster: u32, attribute: u32) {
479 let mut buf = tlv::TlvBuffer::new();
480 let _ = buf.write_array(2);
481 let _ = buf.write_struct_end();
482 self.set_attribute_raw(endpoint, cluster, attribute, &buf.data);
483 }
484
485 pub fn set_cluster_globals(
486 &mut self,
487 endpoint: u16,
488 cluster: u32,
489 revision: u16,
490 feature_map: u32,
491 attribute_ids: &[u32],
492 accepted_cmds: &[u32],
493 generated_cmds: &[u32],
494 ) -> Result<()> {
495 self.set_attribute_u16(endpoint, cluster, ATTR_CLUSTER_REVISION, revision);
496 self.set_attribute_u32(endpoint, cluster, ATTR_FEATURE_MAP, feature_map);
497
498 let mut buf = tlv::TlvBuffer::new();
499 buf.write_array(2)?;
500 for &id in attribute_ids {
501 buf.write_uint32_notag(id)?;
502 }
503 buf.write_uint32_notag(ATTR_ATTRIBUTE_LIST)?;
504 buf.write_uint32_notag(ATTR_FEATURE_MAP)?;
505 buf.write_uint32_notag(ATTR_CLUSTER_REVISION)?;
506 buf.write_uint32_notag(ATTR_EVENT_LIST)?;
507 buf.write_uint32_notag(ATTR_ACCEPTED_CMD_LIST)?;
508 buf.write_uint32_notag(ATTR_GENERATED_CMD_LIST)?;
509 buf.write_struct_end()?;
510 self.set_attribute_raw(endpoint, cluster, ATTR_ATTRIBUTE_LIST, &buf.data);
511
512 self.set_empty_array(endpoint, cluster, ATTR_EVENT_LIST);
513
514 let mut buf = tlv::TlvBuffer::new();
515 buf.write_array(2)?;
516 for &cmd in accepted_cmds {
517 buf.write_uint32_notag(cmd)?;
518 }
519 buf.write_struct_end()?;
520 self.set_attribute_raw(endpoint, cluster, ATTR_ACCEPTED_CMD_LIST, &buf.data);
521
522 let mut buf = tlv::TlvBuffer::new();
523 buf.write_array(2)?;
524 for &cmd in generated_cmds {
525 buf.write_uint32_notag(cmd)?;
526 }
527 buf.write_struct_end()?;
528 self.set_attribute_raw(endpoint, cluster, ATTR_GENERATED_CMD_LIST, &buf.data);
529
530 Ok(())
531 }
532
533 pub fn set_attribute_bool(&mut self, endpoint: u16, cluster: u32, attribute: u32, value: bool) {
534 let mut buf = tlv::TlvBuffer::new();
535 let _ = buf.write_bool(2, value);
536 self.attributes
537 .insert((endpoint, cluster, attribute), buf.data);
538 self.dirty_attributes.insert((endpoint, cluster, attribute));
539 }
540
541 pub fn set_attribute_u8(&mut self, endpoint: u16, cluster: u32, attribute: u32, value: u8) {
542 let mut buf = tlv::TlvBuffer::new();
543 let _ = buf.write_uint8(2, value);
544 self.attributes
545 .insert((endpoint, cluster, attribute), buf.data);
546 self.dirty_attributes.insert((endpoint, cluster, attribute));
547 }
548
549 pub fn set_attribute_u16(&mut self, endpoint: u16, cluster: u32, attribute: u32, value: u16) {
550 let mut buf = tlv::TlvBuffer::new();
551 let _ = buf.write_uint16(2, value);
552 self.attributes
553 .insert((endpoint, cluster, attribute), buf.data);
554 self.dirty_attributes.insert((endpoint, cluster, attribute));
555 }
556
557 pub fn set_attribute_u32(&mut self, endpoint: u16, cluster: u32, attribute: u32, value: u32) {
558 let mut buf = tlv::TlvBuffer::new();
559 let _ = buf.write_uint32(2, value);
560 self.attributes
561 .insert((endpoint, cluster, attribute), buf.data);
562 self.dirty_attributes.insert((endpoint, cluster, attribute));
563 }
564
565 pub fn set_attribute_u64(&mut self, endpoint: u16, cluster: u32, attribute: u32, value: u64) {
566 let mut buf = tlv::TlvBuffer::new();
567 let _ = buf.write_uint64(2, value);
568 self.attributes
569 .insert((endpoint, cluster, attribute), buf.data);
570 self.dirty_attributes.insert((endpoint, cluster, attribute));
571 }
572
573 pub fn set_attribute_string(
574 &mut self,
575 endpoint: u16,
576 cluster: u32,
577 attribute: u32,
578 value: &str,
579 ) {
580 let mut buf = tlv::TlvBuffer::new();
581 let _ = buf.write_string(2, value);
582 self.attributes
583 .insert((endpoint, cluster, attribute), buf.data);
584 self.dirty_attributes.insert((endpoint, cluster, attribute));
585 }
586
587 pub fn set_attribute_raw(&mut self, endpoint: u16, cluster: u32, attribute: u32, value: &[u8]) {
588 self.attributes
589 .insert((endpoint, cluster, attribute), value.to_vec());
590 self.dirty_attributes.insert((endpoint, cluster, attribute));
591 }
592}
593
594
595use std::collections::{HashMap, HashSet};
596
597pub fn attr_set_bool(
598 attributes: &mut HashMap<(u16, u32, u32), Vec<u8>>,
599 dirty: &mut HashSet<(u16, u32, u32)>,
600 ep: u16,
601 cluster: u32,
602 attr: u32,
603 value: bool,
604) {
605 let mut buf = tlv::TlvBuffer::new();
606 let _ = buf.write_bool(2, value);
607 attributes.insert((ep, cluster, attr), buf.data);
608 dirty.insert((ep, cluster, attr));
609}
610
611pub fn attr_get_bool(
612 attributes: &HashMap<(u16, u32, u32), Vec<u8>>,
613 ep: u16,
614 cluster: u32,
615 attr: u32,
616) -> Option<bool> {
617 attributes
618 .get(&(ep, cluster, attr))
619 .and_then(|v| tlv::decode_tlv(v).ok())
620 .map(|item| bool::from(item.value))
621}