1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, serde::Serialize)]
14pub struct DatastoreACLEntry {
15 pub node_id: Option<u64>,
16 pub list_id: Option<u16>,
17 pub acl_entry: Option<DatastoreAccessControlEntry>,
18 pub status_entry: Option<DatastoreStatusEntry>,
19}
20
21#[derive(Debug, serde::Serialize)]
22pub struct DatastoreAccessControlEntry {
23 pub privilege: Option<u8>,
24 pub auth_mode: Option<u8>,
25 pub subjects: Option<Vec<u64>>,
26 pub targets: Option<Vec<DatastoreAccessControlTarget>>,
27}
28
29#[derive(Debug, serde::Serialize)]
30pub struct DatastoreAccessControlTarget {
31 pub cluster: Option<u32>,
32 pub endpoint: Option<u16>,
33 pub device_type: Option<u32>,
34}
35
36#[derive(Debug, serde::Serialize)]
37pub struct DatastoreAdministratorInformationEntry {
38 pub node_id: Option<u64>,
39 pub friendly_name: Option<String>,
40 pub vendor_id: Option<u16>,
41 pub icac: Option<Vec<u8>>,
42}
43
44#[derive(Debug, serde::Serialize)]
45pub struct DatastoreBindingTarget {
46 pub node: Option<u64>,
47 pub group: Option<u8>,
48 pub endpoint: Option<u16>,
49 pub cluster: Option<u32>,
50}
51
52#[derive(Debug, serde::Serialize)]
53pub struct DatastoreEndpointBindingEntry {
54 pub node_id: Option<u64>,
55 pub endpoint_id: Option<u16>,
56 pub list_id: Option<u16>,
57 pub binding: Option<DatastoreBindingTarget>,
58 pub status_entry: Option<DatastoreStatusEntry>,
59}
60
61#[derive(Debug, serde::Serialize)]
62pub struct DatastoreEndpointEntry {
63 pub endpoint_id: Option<u16>,
64 pub node_id: Option<u64>,
65 pub friendly_name: Option<String>,
66 pub status_entry: Option<DatastoreStatusEntry>,
67}
68
69#[derive(Debug, serde::Serialize)]
70pub struct DatastoreEndpointGroupIDEntry {
71 pub node_id: Option<u64>,
72 pub endpoint_id: Option<u16>,
73 pub group_id: Option<u8>,
74 pub status_entry: Option<DatastoreStatusEntry>,
75}
76
77#[derive(Debug, serde::Serialize)]
78pub struct DatastoreGroupInformationEntry {
79 pub group_id: Option<u64>,
80 pub friendly_name: Option<String>,
81 pub group_key_set_id: Option<u16>,
82 pub group_cat: Option<u16>,
83 pub group_cat_version: Option<u16>,
84 pub group_permission: Option<u8>,
85}
86
87#[derive(Debug, serde::Serialize)]
88pub struct DatastoreGroupKeySet {
89 pub group_key_set_id: Option<u16>,
90 pub group_key_security_policy: Option<u8>,
91 pub epoch_key0: Option<Vec<u8>>,
92 pub epoch_start_time0: Option<u8>,
93 pub epoch_key1: Option<Vec<u8>>,
94 pub epoch_start_time1: Option<u8>,
95 pub epoch_key2: Option<Vec<u8>>,
96 pub epoch_start_time2: Option<u8>,
97 pub group_key_multicast_policy: Option<u8>,
98}
99
100#[derive(Debug, serde::Serialize)]
101pub struct DatastoreNodeInformationEntry {
102 pub node_id: Option<u64>,
103 pub friendly_name: Option<String>,
104 pub commissioning_status_entry: Option<DatastoreStatusEntry>,
105}
106
107#[derive(Debug, serde::Serialize)]
108pub struct DatastoreNodeKeySetEntry {
109 pub node_id: Option<u64>,
110 pub group_key_set_id: Option<u16>,
111 pub status_entry: Option<DatastoreStatusEntry>,
112}
113
114#[derive(Debug, serde::Serialize)]
115pub struct DatastoreStatusEntry {
116 pub state: Option<u8>,
117 pub update_timestamp: Option<u64>,
118 pub failure_code: Option<u8>,
119}
120
121pub fn encode_add_key_set(group_key_set: u8) -> anyhow::Result<Vec<u8>> {
125 let tlv = tlv::TlvItemEnc {
126 tag: 0,
127 value: tlv::TlvItemValueEnc::StructInvisible(vec![
128 (0, tlv::TlvItemValueEnc::UInt8(group_key_set)).into(),
129 ]),
130 };
131 Ok(tlv.encode()?)
132}
133
134pub fn encode_update_key_set(group_key_set: u8) -> anyhow::Result<Vec<u8>> {
136 let tlv = tlv::TlvItemEnc {
137 tag: 0,
138 value: tlv::TlvItemValueEnc::StructInvisible(vec![
139 (0, tlv::TlvItemValueEnc::UInt8(group_key_set)).into(),
140 ]),
141 };
142 Ok(tlv.encode()?)
143}
144
145pub fn encode_remove_key_set(group_key_set_id: u16) -> anyhow::Result<Vec<u8>> {
147 let tlv = tlv::TlvItemEnc {
148 tag: 0,
149 value: tlv::TlvItemValueEnc::StructInvisible(vec![
150 (0, tlv::TlvItemValueEnc::UInt16(group_key_set_id)).into(),
151 ]),
152 };
153 Ok(tlv.encode()?)
154}
155
156pub fn encode_add_group(group_id: u8, friendly_name: String, group_key_set_id: Option<u16>, group_cat: Option<u16>, group_cat_version: Option<u16>, group_permission: u8) -> anyhow::Result<Vec<u8>> {
158 let tlv = tlv::TlvItemEnc {
159 tag: 0,
160 value: tlv::TlvItemValueEnc::StructInvisible(vec![
161 (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
162 (1, tlv::TlvItemValueEnc::String(friendly_name)).into(),
163 (2, tlv::TlvItemValueEnc::UInt16(group_key_set_id.unwrap_or(0))).into(),
164 (3, tlv::TlvItemValueEnc::UInt16(group_cat.unwrap_or(0))).into(),
165 (4, tlv::TlvItemValueEnc::UInt16(group_cat_version.unwrap_or(0))).into(),
166 (5, tlv::TlvItemValueEnc::UInt8(group_permission)).into(),
167 ]),
168 };
169 Ok(tlv.encode()?)
170}
171
172pub fn encode_update_group(group_id: u8, friendly_name: Option<String>, group_key_set_id: Option<u16>, group_cat: Option<u16>, group_cat_version: Option<u16>, group_permission: u8) -> anyhow::Result<Vec<u8>> {
174 let tlv = tlv::TlvItemEnc {
175 tag: 0,
176 value: tlv::TlvItemValueEnc::StructInvisible(vec![
177 (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
178 (1, tlv::TlvItemValueEnc::String(friendly_name.unwrap_or("".to_string()))).into(),
179 (2, tlv::TlvItemValueEnc::UInt16(group_key_set_id.unwrap_or(0))).into(),
180 (3, tlv::TlvItemValueEnc::UInt16(group_cat.unwrap_or(0))).into(),
181 (4, tlv::TlvItemValueEnc::UInt16(group_cat_version.unwrap_or(0))).into(),
182 (5, tlv::TlvItemValueEnc::UInt8(group_permission)).into(),
183 ]),
184 };
185 Ok(tlv.encode()?)
186}
187
188pub fn encode_remove_group(group_id: u8) -> anyhow::Result<Vec<u8>> {
190 let tlv = tlv::TlvItemEnc {
191 tag: 0,
192 value: tlv::TlvItemValueEnc::StructInvisible(vec![
193 (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
194 ]),
195 };
196 Ok(tlv.encode()?)
197}
198
199pub fn encode_add_admin(node_id: u64, friendly_name: String, vendor_id: u16, icac: Vec<u8>) -> anyhow::Result<Vec<u8>> {
201 let tlv = tlv::TlvItemEnc {
202 tag: 0,
203 value: tlv::TlvItemValueEnc::StructInvisible(vec![
204 (1, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
205 (2, tlv::TlvItemValueEnc::String(friendly_name)).into(),
206 (3, tlv::TlvItemValueEnc::UInt16(vendor_id)).into(),
207 (4, tlv::TlvItemValueEnc::OctetString(icac)).into(),
208 ]),
209 };
210 Ok(tlv.encode()?)
211}
212
213pub fn encode_update_admin(node_id: Option<u64>, friendly_name: Option<String>, icac: Option<Vec<u8>>) -> anyhow::Result<Vec<u8>> {
215 let tlv = tlv::TlvItemEnc {
216 tag: 0,
217 value: tlv::TlvItemValueEnc::StructInvisible(vec![
218 (0, tlv::TlvItemValueEnc::UInt64(node_id.unwrap_or(0))).into(),
219 (1, tlv::TlvItemValueEnc::String(friendly_name.unwrap_or("".to_string()))).into(),
220 (2, tlv::TlvItemValueEnc::OctetString(icac.unwrap_or(vec![]))).into(),
221 ]),
222 };
223 Ok(tlv.encode()?)
224}
225
226pub fn encode_remove_admin(node_id: u64) -> anyhow::Result<Vec<u8>> {
228 let tlv = tlv::TlvItemEnc {
229 tag: 0,
230 value: tlv::TlvItemValueEnc::StructInvisible(vec![
231 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
232 ]),
233 };
234 Ok(tlv.encode()?)
235}
236
237pub fn encode_add_pending_node(node_id: u64, friendly_name: String) -> anyhow::Result<Vec<u8>> {
239 let tlv = tlv::TlvItemEnc {
240 tag: 0,
241 value: tlv::TlvItemValueEnc::StructInvisible(vec![
242 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
243 (1, tlv::TlvItemValueEnc::String(friendly_name)).into(),
244 ]),
245 };
246 Ok(tlv.encode()?)
247}
248
249pub fn encode_refresh_node(node_id: u64) -> anyhow::Result<Vec<u8>> {
251 let tlv = tlv::TlvItemEnc {
252 tag: 0,
253 value: tlv::TlvItemValueEnc::StructInvisible(vec![
254 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
255 ]),
256 };
257 Ok(tlv.encode()?)
258}
259
260pub fn encode_update_node(node_id: u64, friendly_name: String) -> anyhow::Result<Vec<u8>> {
262 let tlv = tlv::TlvItemEnc {
263 tag: 0,
264 value: tlv::TlvItemValueEnc::StructInvisible(vec![
265 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
266 (1, tlv::TlvItemValueEnc::String(friendly_name)).into(),
267 ]),
268 };
269 Ok(tlv.encode()?)
270}
271
272pub fn encode_remove_node(node_id: u64) -> anyhow::Result<Vec<u8>> {
274 let tlv = tlv::TlvItemEnc {
275 tag: 0,
276 value: tlv::TlvItemValueEnc::StructInvisible(vec![
277 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
278 ]),
279 };
280 Ok(tlv.encode()?)
281}
282
283pub fn encode_update_endpoint_for_node(endpoint_id: u16, node_id: u64, friendly_name: String) -> anyhow::Result<Vec<u8>> {
285 let tlv = tlv::TlvItemEnc {
286 tag: 0,
287 value: tlv::TlvItemValueEnc::StructInvisible(vec![
288 (0, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
289 (1, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
290 (2, tlv::TlvItemValueEnc::String(friendly_name)).into(),
291 ]),
292 };
293 Ok(tlv.encode()?)
294}
295
296pub fn encode_add_group_id_to_endpoint_for_node(node_id: u64, endpoint_id: u16, group_id: u8) -> anyhow::Result<Vec<u8>> {
298 let tlv = tlv::TlvItemEnc {
299 tag: 0,
300 value: tlv::TlvItemValueEnc::StructInvisible(vec![
301 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
302 (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
303 (2, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
304 ]),
305 };
306 Ok(tlv.encode()?)
307}
308
309pub fn encode_remove_group_id_from_endpoint_for_node(node_id: u64, endpoint_id: u16, group_id: u8) -> anyhow::Result<Vec<u8>> {
311 let tlv = tlv::TlvItemEnc {
312 tag: 0,
313 value: tlv::TlvItemValueEnc::StructInvisible(vec![
314 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
315 (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
316 (2, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
317 ]),
318 };
319 Ok(tlv.encode()?)
320}
321
322pub fn encode_add_binding_to_endpoint_for_node(node_id: u64, endpoint_id: u16, binding: u8) -> anyhow::Result<Vec<u8>> {
324 let tlv = tlv::TlvItemEnc {
325 tag: 0,
326 value: tlv::TlvItemValueEnc::StructInvisible(vec![
327 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
328 (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
329 (2, tlv::TlvItemValueEnc::UInt8(binding)).into(),
330 ]),
331 };
332 Ok(tlv.encode()?)
333}
334
335pub fn encode_remove_binding_from_endpoint_for_node(list_id: u16, endpoint_id: u16, node_id: u64) -> anyhow::Result<Vec<u8>> {
337 let tlv = tlv::TlvItemEnc {
338 tag: 0,
339 value: tlv::TlvItemValueEnc::StructInvisible(vec![
340 (0, tlv::TlvItemValueEnc::UInt16(list_id)).into(),
341 (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
342 (2, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
343 ]),
344 };
345 Ok(tlv.encode()?)
346}
347
348pub fn encode_add_acl_to_node(node_id: u64, acl_entry: u8) -> anyhow::Result<Vec<u8>> {
350 let tlv = tlv::TlvItemEnc {
351 tag: 0,
352 value: tlv::TlvItemValueEnc::StructInvisible(vec![
353 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
354 (1, tlv::TlvItemValueEnc::UInt8(acl_entry)).into(),
355 ]),
356 };
357 Ok(tlv.encode()?)
358}
359
360pub fn encode_remove_acl_from_node(list_id: u16, node_id: u64) -> anyhow::Result<Vec<u8>> {
362 let tlv = tlv::TlvItemEnc {
363 tag: 0,
364 value: tlv::TlvItemValueEnc::StructInvisible(vec![
365 (0, tlv::TlvItemValueEnc::UInt16(list_id)).into(),
366 (1, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
367 ]),
368 };
369 Ok(tlv.encode()?)
370}
371
372pub fn decode_anchor_root_ca(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
376 if let tlv::TlvItemValue::OctetString(v) = inp {
377 Ok(v.clone())
378 } else {
379 Err(anyhow::anyhow!("Expected OctetString"))
380 }
381}
382
383pub fn decode_anchor_node_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
385 if let tlv::TlvItemValue::Int(v) = inp {
386 Ok(*v)
387 } else {
388 Err(anyhow::anyhow!("Expected Integer"))
389 }
390}
391
392pub fn decode_anchor_vendor_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
394 if let tlv::TlvItemValue::Int(v) = inp {
395 Ok(*v as u16)
396 } else {
397 Err(anyhow::anyhow!("Expected Integer"))
398 }
399}
400
401pub fn decode_friendly_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
403 if let tlv::TlvItemValue::String(v) = inp {
404 Ok(v.clone())
405 } else {
406 Err(anyhow::anyhow!("Expected String"))
407 }
408}
409
410pub fn decode_group_key_set_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreGroupKeySet>> {
412 let mut res = Vec::new();
413 if let tlv::TlvItemValue::List(v) = inp {
414 for item in v {
415 res.push(DatastoreGroupKeySet {
416 group_key_set_id: item.get_int(&[0]).map(|v| v as u16),
417 group_key_security_policy: item.get_int(&[1]).map(|v| v as u8),
418 epoch_key0: item.get_octet_string_owned(&[2]),
419 epoch_start_time0: item.get_int(&[3]).map(|v| v as u8),
420 epoch_key1: item.get_octet_string_owned(&[4]),
421 epoch_start_time1: item.get_int(&[5]).map(|v| v as u8),
422 epoch_key2: item.get_octet_string_owned(&[6]),
423 epoch_start_time2: item.get_int(&[7]).map(|v| v as u8),
424 group_key_multicast_policy: item.get_int(&[8]).map(|v| v as u8),
425 });
426 }
427 }
428 Ok(res)
429}
430
431pub fn decode_group_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreGroupInformationEntry>> {
433 let mut res = Vec::new();
434 if let tlv::TlvItemValue::List(v) = inp {
435 for item in v {
436 res.push(DatastoreGroupInformationEntry {
437 group_id: item.get_int(&[0]),
438 friendly_name: item.get_string_owned(&[1]),
439 group_key_set_id: item.get_int(&[2]).map(|v| v as u16),
440 group_cat: item.get_int(&[3]).map(|v| v as u16),
441 group_cat_version: item.get_int(&[4]).map(|v| v as u16),
442 group_permission: item.get_int(&[5]).map(|v| v as u8),
443 });
444 }
445 }
446 Ok(res)
447}
448
449pub fn decode_node_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreNodeInformationEntry>> {
451 let mut res = Vec::new();
452 if let tlv::TlvItemValue::List(v) = inp {
453 for item in v {
454 res.push(DatastoreNodeInformationEntry {
455 node_id: item.get_int(&[1]),
456 friendly_name: item.get_string_owned(&[2]),
457 commissioning_status_entry: {
458 if let Some(nested_tlv) = item.get(&[3]) {
459 if let tlv::TlvItemValue::List(_) = nested_tlv {
460 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
461 Some(DatastoreStatusEntry {
462 state: nested_item.get_int(&[0]).map(|v| v as u8),
463 update_timestamp: nested_item.get_int(&[1]),
464 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
465 })
466 } else {
467 None
468 }
469 } else {
470 None
471 }
472 },
473 });
474 }
475 }
476 Ok(res)
477}
478
479pub fn decode_admin_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreAdministratorInformationEntry>> {
481 let mut res = Vec::new();
482 if let tlv::TlvItemValue::List(v) = inp {
483 for item in v {
484 res.push(DatastoreAdministratorInformationEntry {
485 node_id: item.get_int(&[1]),
486 friendly_name: item.get_string_owned(&[2]),
487 vendor_id: item.get_int(&[3]).map(|v| v as u16),
488 icac: item.get_octet_string_owned(&[4]),
489 });
490 }
491 }
492 Ok(res)
493}
494
495pub fn decode_status(inp: &tlv::TlvItemValue) -> anyhow::Result<DatastoreStatusEntry> {
497 if let tlv::TlvItemValue::List(_fields) = inp {
498 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
500 Ok(DatastoreStatusEntry {
501 state: item.get_int(&[0]).map(|v| v as u8),
502 update_timestamp: item.get_int(&[1]),
503 failure_code: item.get_int(&[2]).map(|v| v as u8),
504 })
505 } else {
506 Err(anyhow::anyhow!("Expected struct fields"))
507 }
508}
509
510pub fn decode_endpoint_group_id_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreEndpointGroupIDEntry>> {
512 let mut res = Vec::new();
513 if let tlv::TlvItemValue::List(v) = inp {
514 for item in v {
515 res.push(DatastoreEndpointGroupIDEntry {
516 node_id: item.get_int(&[0]),
517 endpoint_id: item.get_int(&[1]).map(|v| v as u16),
518 group_id: item.get_int(&[2]).map(|v| v as u8),
519 status_entry: {
520 if let Some(nested_tlv) = item.get(&[3]) {
521 if let tlv::TlvItemValue::List(_) = nested_tlv {
522 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
523 Some(DatastoreStatusEntry {
524 state: nested_item.get_int(&[0]).map(|v| v as u8),
525 update_timestamp: nested_item.get_int(&[1]),
526 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
527 })
528 } else {
529 None
530 }
531 } else {
532 None
533 }
534 },
535 });
536 }
537 }
538 Ok(res)
539}
540
541pub fn decode_endpoint_binding_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreEndpointBindingEntry>> {
543 let mut res = Vec::new();
544 if let tlv::TlvItemValue::List(v) = inp {
545 for item in v {
546 res.push(DatastoreEndpointBindingEntry {
547 node_id: item.get_int(&[0]),
548 endpoint_id: item.get_int(&[1]).map(|v| v as u16),
549 list_id: item.get_int(&[2]).map(|v| v as u16),
550 binding: {
551 if let Some(nested_tlv) = item.get(&[3]) {
552 if let tlv::TlvItemValue::List(_) = nested_tlv {
553 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
554 Some(DatastoreBindingTarget {
555 node: nested_item.get_int(&[1]),
556 group: nested_item.get_int(&[2]).map(|v| v as u8),
557 endpoint: nested_item.get_int(&[3]).map(|v| v as u16),
558 cluster: nested_item.get_int(&[4]).map(|v| v as u32),
559 })
560 } else {
561 None
562 }
563 } else {
564 None
565 }
566 },
567 status_entry: {
568 if let Some(nested_tlv) = item.get(&[4]) {
569 if let tlv::TlvItemValue::List(_) = nested_tlv {
570 let nested_item = tlv::TlvItem { tag: 4, value: nested_tlv.clone() };
571 Some(DatastoreStatusEntry {
572 state: nested_item.get_int(&[0]).map(|v| v as u8),
573 update_timestamp: nested_item.get_int(&[1]),
574 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
575 })
576 } else {
577 None
578 }
579 } else {
580 None
581 }
582 },
583 });
584 }
585 }
586 Ok(res)
587}
588
589pub fn decode_node_key_set_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreNodeKeySetEntry>> {
591 let mut res = Vec::new();
592 if let tlv::TlvItemValue::List(v) = inp {
593 for item in v {
594 res.push(DatastoreNodeKeySetEntry {
595 node_id: item.get_int(&[0]),
596 group_key_set_id: item.get_int(&[1]).map(|v| v as u16),
597 status_entry: {
598 if let Some(nested_tlv) = item.get(&[2]) {
599 if let tlv::TlvItemValue::List(_) = nested_tlv {
600 let nested_item = tlv::TlvItem { tag: 2, value: nested_tlv.clone() };
601 Some(DatastoreStatusEntry {
602 state: nested_item.get_int(&[0]).map(|v| v as u8),
603 update_timestamp: nested_item.get_int(&[1]),
604 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
605 })
606 } else {
607 None
608 }
609 } else {
610 None
611 }
612 },
613 });
614 }
615 }
616 Ok(res)
617}
618
619pub fn decode_node_acl_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreACLEntry>> {
621 let mut res = Vec::new();
622 if let tlv::TlvItemValue::List(v) = inp {
623 for item in v {
624 res.push(DatastoreACLEntry {
625 node_id: item.get_int(&[0]),
626 list_id: item.get_int(&[1]).map(|v| v as u16),
627 acl_entry: {
628 if let Some(nested_tlv) = item.get(&[2]) {
629 if let tlv::TlvItemValue::List(_) = nested_tlv {
630 let nested_item = tlv::TlvItem { tag: 2, value: nested_tlv.clone() };
631 Some(DatastoreAccessControlEntry {
632 privilege: nested_item.get_int(&[1]).map(|v| v as u8),
633 auth_mode: nested_item.get_int(&[2]).map(|v| v as u8),
634 subjects: {
635 if let Some(tlv::TlvItemValue::List(l)) = nested_item.get(&[3]) {
636 let items: Vec<u64> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v) } else { None } }).collect();
637 Some(items)
638 } else {
639 None
640 }
641 },
642 targets: {
643 if let Some(tlv::TlvItemValue::List(l)) = nested_item.get(&[4]) {
644 let mut items = Vec::new();
645 for list_item in l {
646 items.push(DatastoreAccessControlTarget {
647 cluster: list_item.get_int(&[0]).map(|v| v as u32),
648 endpoint: list_item.get_int(&[1]).map(|v| v as u16),
649 device_type: list_item.get_int(&[2]).map(|v| v as u32),
650 });
651 }
652 Some(items)
653 } else {
654 None
655 }
656 },
657 })
658 } else {
659 None
660 }
661 } else {
662 None
663 }
664 },
665 status_entry: {
666 if let Some(nested_tlv) = item.get(&[3]) {
667 if let tlv::TlvItemValue::List(_) = nested_tlv {
668 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
669 Some(DatastoreStatusEntry {
670 state: nested_item.get_int(&[0]).map(|v| v as u8),
671 update_timestamp: nested_item.get_int(&[1]),
672 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
673 })
674 } else {
675 None
676 }
677 } else {
678 None
679 }
680 },
681 });
682 }
683 }
684 Ok(res)
685}
686
687pub fn decode_node_endpoint_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreEndpointEntry>> {
689 let mut res = Vec::new();
690 if let tlv::TlvItemValue::List(v) = inp {
691 for item in v {
692 res.push(DatastoreEndpointEntry {
693 endpoint_id: item.get_int(&[0]).map(|v| v as u16),
694 node_id: item.get_int(&[1]),
695 friendly_name: item.get_string_owned(&[2]),
696 status_entry: {
697 if let Some(nested_tlv) = item.get(&[3]) {
698 if let tlv::TlvItemValue::List(_) = nested_tlv {
699 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
700 Some(DatastoreStatusEntry {
701 state: nested_item.get_int(&[0]).map(|v| v as u8),
702 update_timestamp: nested_item.get_int(&[1]),
703 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
704 })
705 } else {
706 None
707 }
708 } else {
709 None
710 }
711 },
712 });
713 }
714 }
715 Ok(res)
716}
717
718
719pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
731 if cluster_id != 0x0752 {
733 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0752, got {}\"}}", cluster_id);
734 }
735
736 match attribute_id {
737 0x0000 => {
738 match decode_anchor_root_ca(tlv_value) {
739 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
740 Err(e) => format!("{{\"error\": \"{}\"}}", e),
741 }
742 }
743 0x0001 => {
744 match decode_anchor_node_id(tlv_value) {
745 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
746 Err(e) => format!("{{\"error\": \"{}\"}}", e),
747 }
748 }
749 0x0002 => {
750 match decode_anchor_vendor_id(tlv_value) {
751 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
752 Err(e) => format!("{{\"error\": \"{}\"}}", e),
753 }
754 }
755 0x0003 => {
756 match decode_friendly_name(tlv_value) {
757 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
758 Err(e) => format!("{{\"error\": \"{}\"}}", e),
759 }
760 }
761 0x0004 => {
762 match decode_group_key_set_list(tlv_value) {
763 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
764 Err(e) => format!("{{\"error\": \"{}\"}}", e),
765 }
766 }
767 0x0005 => {
768 match decode_group_list(tlv_value) {
769 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
770 Err(e) => format!("{{\"error\": \"{}\"}}", e),
771 }
772 }
773 0x0006 => {
774 match decode_node_list(tlv_value) {
775 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
776 Err(e) => format!("{{\"error\": \"{}\"}}", e),
777 }
778 }
779 0x0007 => {
780 match decode_admin_list(tlv_value) {
781 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
782 Err(e) => format!("{{\"error\": \"{}\"}}", e),
783 }
784 }
785 0x0008 => {
786 match decode_status(tlv_value) {
787 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
788 Err(e) => format!("{{\"error\": \"{}\"}}", e),
789 }
790 }
791 0x0009 => {
792 match decode_endpoint_group_id_list(tlv_value) {
793 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
794 Err(e) => format!("{{\"error\": \"{}\"}}", e),
795 }
796 }
797 0x000A => {
798 match decode_endpoint_binding_list(tlv_value) {
799 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
800 Err(e) => format!("{{\"error\": \"{}\"}}", e),
801 }
802 }
803 0x000B => {
804 match decode_node_key_set_list(tlv_value) {
805 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
806 Err(e) => format!("{{\"error\": \"{}\"}}", e),
807 }
808 }
809 0x000C => {
810 match decode_node_acl_list(tlv_value) {
811 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
812 Err(e) => format!("{{\"error\": \"{}\"}}", e),
813 }
814 }
815 0x000D => {
816 match decode_node_endpoint_list(tlv_value) {
817 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
818 Err(e) => format!("{{\"error\": \"{}\"}}", e),
819 }
820 }
821 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
822 }
823}
824
825pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
830 vec![
831 (0x0000, "AnchorRootCA"),
832 (0x0001, "AnchorNodeID"),
833 (0x0002, "AnchorVendorID"),
834 (0x0003, "FriendlyName"),
835 (0x0004, "GroupKeySetList"),
836 (0x0005, "GroupList"),
837 (0x0006, "NodeList"),
838 (0x0007, "AdminList"),
839 (0x0008, "Status"),
840 (0x0009, "EndpointGroupIDList"),
841 (0x000A, "EndpointBindingList"),
842 (0x000B, "NodeKeySetList"),
843 (0x000C, "NodeACLList"),
844 (0x000D, "NodeEndpointList"),
845 ]
846}
847