1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11use crate::clusters::helpers::{serialize_opt_bytes_as_hex};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
17#[repr(u8)]
18pub enum DatastoreAccessControlEntryAuthMode {
19 Pase = 1,
21 Case = 2,
23 Group = 3,
25}
26
27impl DatastoreAccessControlEntryAuthMode {
28 pub fn from_u8(value: u8) -> Option<Self> {
30 match value {
31 1 => Some(DatastoreAccessControlEntryAuthMode::Pase),
32 2 => Some(DatastoreAccessControlEntryAuthMode::Case),
33 3 => Some(DatastoreAccessControlEntryAuthMode::Group),
34 _ => None,
35 }
36 }
37
38 pub fn to_u8(self) -> u8 {
40 self as u8
41 }
42}
43
44impl From<DatastoreAccessControlEntryAuthMode> for u8 {
45 fn from(val: DatastoreAccessControlEntryAuthMode) -> Self {
46 val as u8
47 }
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
51#[repr(u8)]
52pub enum DatastoreAccessControlEntryPrivilege {
53 View = 1,
55 Proxyview = 2,
56 Operate = 3,
58 Manage = 4,
60 Administer = 5,
62}
63
64impl DatastoreAccessControlEntryPrivilege {
65 pub fn from_u8(value: u8) -> Option<Self> {
67 match value {
68 1 => Some(DatastoreAccessControlEntryPrivilege::View),
69 2 => Some(DatastoreAccessControlEntryPrivilege::Proxyview),
70 3 => Some(DatastoreAccessControlEntryPrivilege::Operate),
71 4 => Some(DatastoreAccessControlEntryPrivilege::Manage),
72 5 => Some(DatastoreAccessControlEntryPrivilege::Administer),
73 _ => None,
74 }
75 }
76
77 pub fn to_u8(self) -> u8 {
79 self as u8
80 }
81}
82
83impl From<DatastoreAccessControlEntryPrivilege> for u8 {
84 fn from(val: DatastoreAccessControlEntryPrivilege) -> Self {
85 val as u8
86 }
87}
88
89#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
90#[repr(u8)]
91pub enum DatastoreGroupKeyMulticastPolicy {
92 Pergroupid = 0,
94 Allnodes = 1,
96}
97
98impl DatastoreGroupKeyMulticastPolicy {
99 pub fn from_u8(value: u8) -> Option<Self> {
101 match value {
102 0 => Some(DatastoreGroupKeyMulticastPolicy::Pergroupid),
103 1 => Some(DatastoreGroupKeyMulticastPolicy::Allnodes),
104 _ => None,
105 }
106 }
107
108 pub fn to_u8(self) -> u8 {
110 self as u8
111 }
112}
113
114impl From<DatastoreGroupKeyMulticastPolicy> for u8 {
115 fn from(val: DatastoreGroupKeyMulticastPolicy) -> Self {
116 val as u8
117 }
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
121#[repr(u8)]
122pub enum DatastoreGroupKeySecurityPolicy {
123 Trustfirst = 0,
125}
126
127impl DatastoreGroupKeySecurityPolicy {
128 pub fn from_u8(value: u8) -> Option<Self> {
130 match value {
131 0 => Some(DatastoreGroupKeySecurityPolicy::Trustfirst),
132 _ => None,
133 }
134 }
135
136 pub fn to_u8(self) -> u8 {
138 self as u8
139 }
140}
141
142impl From<DatastoreGroupKeySecurityPolicy> for u8 {
143 fn from(val: DatastoreGroupKeySecurityPolicy) -> Self {
144 val as u8
145 }
146}
147
148#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
149#[repr(u8)]
150pub enum DatastoreState {
151 Pending = 0,
153 Committed = 1,
155 Deletepending = 2,
157 Commitfailed = 3,
159}
160
161impl DatastoreState {
162 pub fn from_u8(value: u8) -> Option<Self> {
164 match value {
165 0 => Some(DatastoreState::Pending),
166 1 => Some(DatastoreState::Committed),
167 2 => Some(DatastoreState::Deletepending),
168 3 => Some(DatastoreState::Commitfailed),
169 _ => None,
170 }
171 }
172
173 pub fn to_u8(self) -> u8 {
175 self as u8
176 }
177}
178
179impl From<DatastoreState> for u8 {
180 fn from(val: DatastoreState) -> Self {
181 val as u8
182 }
183}
184
185#[derive(Debug, serde::Serialize)]
188pub struct DatastoreACLEntry {
189 pub node_id: Option<u64>,
190 pub list_id: Option<u16>,
191 pub acl_entry: Option<DatastoreAccessControlEntry>,
192 pub status_entry: Option<DatastoreStatusEntry>,
193}
194
195#[derive(Debug, serde::Serialize)]
196pub struct DatastoreAccessControlEntry {
197 pub privilege: Option<DatastoreAccessControlEntryPrivilege>,
198 pub auth_mode: Option<DatastoreAccessControlEntryAuthMode>,
199 pub subjects: Option<Vec<u64>>,
200 pub targets: Option<Vec<DatastoreAccessControlTarget>>,
201}
202
203#[derive(Debug, serde::Serialize)]
204pub struct DatastoreAccessControlTarget {
205 pub cluster: Option<u32>,
206 pub endpoint: Option<u16>,
207 pub device_type: Option<u32>,
208}
209
210#[derive(Debug, serde::Serialize)]
211pub struct DatastoreAdministratorInformationEntry {
212 pub node_id: Option<u64>,
213 pub friendly_name: Option<String>,
214 pub vendor_id: Option<u16>,
215 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
216 pub icac: Option<Vec<u8>>,
217}
218
219#[derive(Debug, serde::Serialize)]
220pub struct DatastoreBindingTarget {
221 pub node: Option<u64>,
222 pub group: Option<u8>,
223 pub endpoint: Option<u16>,
224 pub cluster: Option<u32>,
225}
226
227#[derive(Debug, serde::Serialize)]
228pub struct DatastoreEndpointBindingEntry {
229 pub node_id: Option<u64>,
230 pub endpoint_id: Option<u16>,
231 pub list_id: Option<u16>,
232 pub binding: Option<DatastoreBindingTarget>,
233 pub status_entry: Option<DatastoreStatusEntry>,
234}
235
236#[derive(Debug, serde::Serialize)]
237pub struct DatastoreEndpointEntry {
238 pub endpoint_id: Option<u16>,
239 pub node_id: Option<u64>,
240 pub friendly_name: Option<String>,
241 pub status_entry: Option<DatastoreStatusEntry>,
242}
243
244#[derive(Debug, serde::Serialize)]
245pub struct DatastoreEndpointGroupIDEntry {
246 pub node_id: Option<u64>,
247 pub endpoint_id: Option<u16>,
248 pub group_id: Option<u8>,
249 pub status_entry: Option<DatastoreStatusEntry>,
250}
251
252#[derive(Debug, serde::Serialize)]
253pub struct DatastoreGroupInformationEntry {
254 pub group_id: Option<u64>,
255 pub friendly_name: Option<String>,
256 pub group_key_set_id: Option<u16>,
257 pub group_cat: Option<u16>,
258 pub group_cat_version: Option<u16>,
259 pub group_permission: Option<DatastoreAccessControlEntryPrivilege>,
260}
261
262#[derive(Debug, serde::Serialize)]
263pub struct DatastoreGroupKeySet {
264 pub group_key_set_id: Option<u16>,
265 pub group_key_security_policy: Option<DatastoreGroupKeySecurityPolicy>,
266 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
267 pub epoch_key0: Option<Vec<u8>>,
268 pub epoch_start_time0: Option<u64>,
269 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
270 pub epoch_key1: Option<Vec<u8>>,
271 pub epoch_start_time1: Option<u64>,
272 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
273 pub epoch_key2: Option<Vec<u8>>,
274 pub epoch_start_time2: Option<u64>,
275 pub group_key_multicast_policy: Option<DatastoreGroupKeyMulticastPolicy>,
276}
277
278#[derive(Debug, serde::Serialize)]
279pub struct DatastoreNodeInformationEntry {
280 pub node_id: Option<u64>,
281 pub friendly_name: Option<String>,
282 pub commissioning_status_entry: Option<DatastoreStatusEntry>,
283}
284
285#[derive(Debug, serde::Serialize)]
286pub struct DatastoreNodeKeySetEntry {
287 pub node_id: Option<u64>,
288 pub group_key_set_id: Option<u16>,
289 pub status_entry: Option<DatastoreStatusEntry>,
290}
291
292#[derive(Debug, serde::Serialize)]
293pub struct DatastoreStatusEntry {
294 pub state: Option<DatastoreState>,
295 pub update_timestamp: Option<u64>,
296 pub failure_code: Option<u8>,
297}
298
299pub fn encode_add_key_set(group_key_set: DatastoreGroupKeySet) -> anyhow::Result<Vec<u8>> {
303 let mut group_key_set_fields = Vec::new();
305 if let Some(x) = group_key_set.group_key_set_id { group_key_set_fields.push((0, tlv::TlvItemValueEnc::UInt16(x)).into()); }
306 if let Some(x) = group_key_set.group_key_security_policy { group_key_set_fields.push((1, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
307 if let Some(x) = group_key_set.epoch_key0 { group_key_set_fields.push((2, tlv::TlvItemValueEnc::OctetString(x.clone())).into()); }
308 if let Some(x) = group_key_set.epoch_start_time0 { group_key_set_fields.push((3, tlv::TlvItemValueEnc::UInt64(x)).into()); }
309 if let Some(x) = group_key_set.epoch_key1 { group_key_set_fields.push((4, tlv::TlvItemValueEnc::OctetString(x.clone())).into()); }
310 if let Some(x) = group_key_set.epoch_start_time1 { group_key_set_fields.push((5, tlv::TlvItemValueEnc::UInt64(x)).into()); }
311 if let Some(x) = group_key_set.epoch_key2 { group_key_set_fields.push((6, tlv::TlvItemValueEnc::OctetString(x.clone())).into()); }
312 if let Some(x) = group_key_set.epoch_start_time2 { group_key_set_fields.push((7, tlv::TlvItemValueEnc::UInt64(x)).into()); }
313 if let Some(x) = group_key_set.group_key_multicast_policy { group_key_set_fields.push((8, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
314 let tlv = tlv::TlvItemEnc {
315 tag: 0,
316 value: tlv::TlvItemValueEnc::StructInvisible(vec![
317 (0, tlv::TlvItemValueEnc::StructInvisible(group_key_set_fields)).into(),
318 ]),
319 };
320 Ok(tlv.encode()?)
321}
322
323pub fn encode_update_key_set(group_key_set: DatastoreGroupKeySet) -> anyhow::Result<Vec<u8>> {
325 let mut group_key_set_fields = Vec::new();
327 if let Some(x) = group_key_set.group_key_set_id { group_key_set_fields.push((0, tlv::TlvItemValueEnc::UInt16(x)).into()); }
328 if let Some(x) = group_key_set.group_key_security_policy { group_key_set_fields.push((1, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
329 if let Some(x) = group_key_set.epoch_key0 { group_key_set_fields.push((2, tlv::TlvItemValueEnc::OctetString(x.clone())).into()); }
330 if let Some(x) = group_key_set.epoch_start_time0 { group_key_set_fields.push((3, tlv::TlvItemValueEnc::UInt64(x)).into()); }
331 if let Some(x) = group_key_set.epoch_key1 { group_key_set_fields.push((4, tlv::TlvItemValueEnc::OctetString(x.clone())).into()); }
332 if let Some(x) = group_key_set.epoch_start_time1 { group_key_set_fields.push((5, tlv::TlvItemValueEnc::UInt64(x)).into()); }
333 if let Some(x) = group_key_set.epoch_key2 { group_key_set_fields.push((6, tlv::TlvItemValueEnc::OctetString(x.clone())).into()); }
334 if let Some(x) = group_key_set.epoch_start_time2 { group_key_set_fields.push((7, tlv::TlvItemValueEnc::UInt64(x)).into()); }
335 if let Some(x) = group_key_set.group_key_multicast_policy { group_key_set_fields.push((8, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
336 let tlv = tlv::TlvItemEnc {
337 tag: 0,
338 value: tlv::TlvItemValueEnc::StructInvisible(vec![
339 (0, tlv::TlvItemValueEnc::StructInvisible(group_key_set_fields)).into(),
340 ]),
341 };
342 Ok(tlv.encode()?)
343}
344
345pub fn encode_remove_key_set(group_key_set_id: u16) -> anyhow::Result<Vec<u8>> {
347 let tlv = tlv::TlvItemEnc {
348 tag: 0,
349 value: tlv::TlvItemValueEnc::StructInvisible(vec![
350 (0, tlv::TlvItemValueEnc::UInt16(group_key_set_id)).into(),
351 ]),
352 };
353 Ok(tlv.encode()?)
354}
355
356pub 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: DatastoreAccessControlEntryPrivilege) -> anyhow::Result<Vec<u8>> {
358 let tlv = tlv::TlvItemEnc {
359 tag: 0,
360 value: tlv::TlvItemValueEnc::StructInvisible(vec![
361 (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
362 (1, tlv::TlvItemValueEnc::String(friendly_name)).into(),
363 (2, tlv::TlvItemValueEnc::UInt16(group_key_set_id.unwrap_or(0))).into(),
364 (3, tlv::TlvItemValueEnc::UInt16(group_cat.unwrap_or(0))).into(),
365 (4, tlv::TlvItemValueEnc::UInt16(group_cat_version.unwrap_or(0))).into(),
366 (5, tlv::TlvItemValueEnc::UInt8(group_permission.to_u8())).into(),
367 ]),
368 };
369 Ok(tlv.encode()?)
370}
371
372pub 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: Option<DatastoreAccessControlEntryPrivilege>) -> anyhow::Result<Vec<u8>> {
374 let tlv = tlv::TlvItemEnc {
375 tag: 0,
376 value: tlv::TlvItemValueEnc::StructInvisible(vec![
377 (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
378 (1, tlv::TlvItemValueEnc::String(friendly_name.unwrap_or("".to_string()))).into(),
379 (2, tlv::TlvItemValueEnc::UInt16(group_key_set_id.unwrap_or(0))).into(),
380 (3, tlv::TlvItemValueEnc::UInt16(group_cat.unwrap_or(0))).into(),
381 (4, tlv::TlvItemValueEnc::UInt16(group_cat_version.unwrap_or(0))).into(),
382 (5, tlv::TlvItemValueEnc::UInt8(group_permission.map(|e| e.to_u8()).unwrap_or(0))).into(),
383 ]),
384 };
385 Ok(tlv.encode()?)
386}
387
388pub fn encode_remove_group(group_id: u8) -> anyhow::Result<Vec<u8>> {
390 let tlv = tlv::TlvItemEnc {
391 tag: 0,
392 value: tlv::TlvItemValueEnc::StructInvisible(vec![
393 (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
394 ]),
395 };
396 Ok(tlv.encode()?)
397}
398
399pub fn encode_add_admin(node_id: u64, friendly_name: String, vendor_id: u16, icac: Vec<u8>) -> anyhow::Result<Vec<u8>> {
401 let tlv = tlv::TlvItemEnc {
402 tag: 0,
403 value: tlv::TlvItemValueEnc::StructInvisible(vec![
404 (1, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
405 (2, tlv::TlvItemValueEnc::String(friendly_name)).into(),
406 (3, tlv::TlvItemValueEnc::UInt16(vendor_id)).into(),
407 (4, tlv::TlvItemValueEnc::OctetString(icac)).into(),
408 ]),
409 };
410 Ok(tlv.encode()?)
411}
412
413pub fn encode_update_admin(node_id: Option<u64>, friendly_name: Option<String>, icac: Option<Vec<u8>>) -> anyhow::Result<Vec<u8>> {
415 let tlv = tlv::TlvItemEnc {
416 tag: 0,
417 value: tlv::TlvItemValueEnc::StructInvisible(vec![
418 (0, tlv::TlvItemValueEnc::UInt64(node_id.unwrap_or(0))).into(),
419 (1, tlv::TlvItemValueEnc::String(friendly_name.unwrap_or("".to_string()))).into(),
420 (2, tlv::TlvItemValueEnc::OctetString(icac.unwrap_or(vec![]))).into(),
421 ]),
422 };
423 Ok(tlv.encode()?)
424}
425
426pub fn encode_remove_admin(node_id: u64) -> anyhow::Result<Vec<u8>> {
428 let tlv = tlv::TlvItemEnc {
429 tag: 0,
430 value: tlv::TlvItemValueEnc::StructInvisible(vec![
431 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
432 ]),
433 };
434 Ok(tlv.encode()?)
435}
436
437pub fn encode_add_pending_node(node_id: u64, friendly_name: String) -> anyhow::Result<Vec<u8>> {
439 let tlv = tlv::TlvItemEnc {
440 tag: 0,
441 value: tlv::TlvItemValueEnc::StructInvisible(vec![
442 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
443 (1, tlv::TlvItemValueEnc::String(friendly_name)).into(),
444 ]),
445 };
446 Ok(tlv.encode()?)
447}
448
449pub fn encode_refresh_node(node_id: u64) -> anyhow::Result<Vec<u8>> {
451 let tlv = tlv::TlvItemEnc {
452 tag: 0,
453 value: tlv::TlvItemValueEnc::StructInvisible(vec![
454 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
455 ]),
456 };
457 Ok(tlv.encode()?)
458}
459
460pub fn encode_update_node(node_id: u64, friendly_name: String) -> anyhow::Result<Vec<u8>> {
462 let tlv = tlv::TlvItemEnc {
463 tag: 0,
464 value: tlv::TlvItemValueEnc::StructInvisible(vec![
465 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
466 (1, tlv::TlvItemValueEnc::String(friendly_name)).into(),
467 ]),
468 };
469 Ok(tlv.encode()?)
470}
471
472pub fn encode_remove_node(node_id: u64) -> anyhow::Result<Vec<u8>> {
474 let tlv = tlv::TlvItemEnc {
475 tag: 0,
476 value: tlv::TlvItemValueEnc::StructInvisible(vec![
477 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
478 ]),
479 };
480 Ok(tlv.encode()?)
481}
482
483pub fn encode_update_endpoint_for_node(endpoint_id: u16, node_id: u64, friendly_name: String) -> anyhow::Result<Vec<u8>> {
485 let tlv = tlv::TlvItemEnc {
486 tag: 0,
487 value: tlv::TlvItemValueEnc::StructInvisible(vec![
488 (0, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
489 (1, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
490 (2, tlv::TlvItemValueEnc::String(friendly_name)).into(),
491 ]),
492 };
493 Ok(tlv.encode()?)
494}
495
496pub fn encode_add_group_id_to_endpoint_for_node(node_id: u64, endpoint_id: u16, group_id: u8) -> anyhow::Result<Vec<u8>> {
498 let tlv = tlv::TlvItemEnc {
499 tag: 0,
500 value: tlv::TlvItemValueEnc::StructInvisible(vec![
501 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
502 (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
503 (2, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
504 ]),
505 };
506 Ok(tlv.encode()?)
507}
508
509pub fn encode_remove_group_id_from_endpoint_for_node(node_id: u64, endpoint_id: u16, group_id: u8) -> anyhow::Result<Vec<u8>> {
511 let tlv = tlv::TlvItemEnc {
512 tag: 0,
513 value: tlv::TlvItemValueEnc::StructInvisible(vec![
514 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
515 (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
516 (2, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
517 ]),
518 };
519 Ok(tlv.encode()?)
520}
521
522pub fn encode_add_binding_to_endpoint_for_node(node_id: u64, endpoint_id: u16, binding: DatastoreBindingTarget) -> anyhow::Result<Vec<u8>> {
524 let mut binding_fields = Vec::new();
526 if let Some(x) = binding.node { binding_fields.push((1, tlv::TlvItemValueEnc::UInt64(x)).into()); }
527 if let Some(x) = binding.endpoint { binding_fields.push((3, tlv::TlvItemValueEnc::UInt16(x)).into()); }
529 if let Some(x) = binding.cluster { binding_fields.push((4, tlv::TlvItemValueEnc::UInt32(x)).into()); }
530 let tlv = tlv::TlvItemEnc {
531 tag: 0,
532 value: tlv::TlvItemValueEnc::StructInvisible(vec![
533 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
534 (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
535 (2, tlv::TlvItemValueEnc::StructInvisible(binding_fields)).into(),
536 ]),
537 };
538 Ok(tlv.encode()?)
539}
540
541pub fn encode_remove_binding_from_endpoint_for_node(list_id: u16, endpoint_id: u16, node_id: u64) -> anyhow::Result<Vec<u8>> {
543 let tlv = tlv::TlvItemEnc {
544 tag: 0,
545 value: tlv::TlvItemValueEnc::StructInvisible(vec![
546 (0, tlv::TlvItemValueEnc::UInt16(list_id)).into(),
547 (1, tlv::TlvItemValueEnc::UInt16(endpoint_id)).into(),
548 (2, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
549 ]),
550 };
551 Ok(tlv.encode()?)
552}
553
554pub fn encode_add_acl_to_node(node_id: u64, acl_entry: DatastoreAccessControlEntry) -> anyhow::Result<Vec<u8>> {
556 let mut acl_entry_fields = Vec::new();
558 if let Some(x) = acl_entry.privilege { acl_entry_fields.push((1, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
559 if let Some(x) = acl_entry.auth_mode { acl_entry_fields.push((2, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
560 if let Some(listv) = acl_entry.subjects { acl_entry_fields.push((3, tlv::TlvItemValueEnc::StructAnon(listv.into_iter().map(|x| (0, tlv::TlvItemValueEnc::UInt64(x)).into()).collect())).into()); }
561 if let Some(listv) = acl_entry.targets {
562 let inner_vec: Vec<_> = listv.into_iter().map(|inner| {
563 let mut nested_fields = Vec::new();
564 if let Some(x) = inner.cluster { nested_fields.push((0, tlv::TlvItemValueEnc::UInt32(x)).into()); }
565 if let Some(x) = inner.endpoint { nested_fields.push((1, tlv::TlvItemValueEnc::UInt16(x)).into()); }
566 if let Some(x) = inner.device_type { nested_fields.push((2, tlv::TlvItemValueEnc::UInt32(x)).into()); }
567 (0, tlv::TlvItemValueEnc::StructAnon(nested_fields)).into()
568 }).collect();
569 acl_entry_fields.push((4, tlv::TlvItemValueEnc::Array(inner_vec)).into());
570 }
571 let tlv = tlv::TlvItemEnc {
572 tag: 0,
573 value: tlv::TlvItemValueEnc::StructInvisible(vec![
574 (0, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
575 (1, tlv::TlvItemValueEnc::StructInvisible(acl_entry_fields)).into(),
576 ]),
577 };
578 Ok(tlv.encode()?)
579}
580
581pub fn encode_remove_acl_from_node(list_id: u16, node_id: u64) -> anyhow::Result<Vec<u8>> {
583 let tlv = tlv::TlvItemEnc {
584 tag: 0,
585 value: tlv::TlvItemValueEnc::StructInvisible(vec![
586 (0, tlv::TlvItemValueEnc::UInt16(list_id)).into(),
587 (1, tlv::TlvItemValueEnc::UInt64(node_id)).into(),
588 ]),
589 };
590 Ok(tlv.encode()?)
591}
592
593pub fn decode_anchor_root_ca(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
597 if let tlv::TlvItemValue::OctetString(v) = inp {
598 Ok(v.clone())
599 } else {
600 Err(anyhow::anyhow!("Expected OctetString"))
601 }
602}
603
604pub fn decode_anchor_node_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
606 if let tlv::TlvItemValue::Int(v) = inp {
607 Ok(*v)
608 } else {
609 Err(anyhow::anyhow!("Expected UInt64"))
610 }
611}
612
613pub fn decode_anchor_vendor_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
615 if let tlv::TlvItemValue::Int(v) = inp {
616 Ok(*v as u16)
617 } else {
618 Err(anyhow::anyhow!("Expected UInt16"))
619 }
620}
621
622pub fn decode_friendly_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
624 if let tlv::TlvItemValue::String(v) = inp {
625 Ok(v.clone())
626 } else {
627 Err(anyhow::anyhow!("Expected String"))
628 }
629}
630
631pub fn decode_group_key_set_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreGroupKeySet>> {
633 let mut res = Vec::new();
634 if let tlv::TlvItemValue::List(v) = inp {
635 for item in v {
636 res.push(DatastoreGroupKeySet {
637 group_key_set_id: item.get_int(&[0]).map(|v| v as u16),
638 group_key_security_policy: item.get_int(&[1]).and_then(|v| DatastoreGroupKeySecurityPolicy::from_u8(v as u8)),
639 epoch_key0: item.get_octet_string_owned(&[2]),
640 epoch_start_time0: item.get_int(&[3]),
641 epoch_key1: item.get_octet_string_owned(&[4]),
642 epoch_start_time1: item.get_int(&[5]),
643 epoch_key2: item.get_octet_string_owned(&[6]),
644 epoch_start_time2: item.get_int(&[7]),
645 group_key_multicast_policy: item.get_int(&[8]).and_then(|v| DatastoreGroupKeyMulticastPolicy::from_u8(v as u8)),
646 });
647 }
648 }
649 Ok(res)
650}
651
652pub fn decode_group_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreGroupInformationEntry>> {
654 let mut res = Vec::new();
655 if let tlv::TlvItemValue::List(v) = inp {
656 for item in v {
657 res.push(DatastoreGroupInformationEntry {
658 group_id: item.get_int(&[0]),
659 friendly_name: item.get_string_owned(&[1]),
660 group_key_set_id: item.get_int(&[2]).map(|v| v as u16),
661 group_cat: item.get_int(&[3]).map(|v| v as u16),
662 group_cat_version: item.get_int(&[4]).map(|v| v as u16),
663 group_permission: item.get_int(&[5]).and_then(|v| DatastoreAccessControlEntryPrivilege::from_u8(v as u8)),
664 });
665 }
666 }
667 Ok(res)
668}
669
670pub fn decode_node_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreNodeInformationEntry>> {
672 let mut res = Vec::new();
673 if let tlv::TlvItemValue::List(v) = inp {
674 for item in v {
675 res.push(DatastoreNodeInformationEntry {
676 node_id: item.get_int(&[1]),
677 friendly_name: item.get_string_owned(&[2]),
678 commissioning_status_entry: {
679 if let Some(nested_tlv) = item.get(&[3]) {
680 if let tlv::TlvItemValue::List(_) = nested_tlv {
681 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
682 Some(DatastoreStatusEntry {
683 state: nested_item.get_int(&[0]).and_then(|v| DatastoreState::from_u8(v as u8)),
684 update_timestamp: nested_item.get_int(&[1]),
685 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
686 })
687 } else {
688 None
689 }
690 } else {
691 None
692 }
693 },
694 });
695 }
696 }
697 Ok(res)
698}
699
700pub fn decode_admin_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreAdministratorInformationEntry>> {
702 let mut res = Vec::new();
703 if let tlv::TlvItemValue::List(v) = inp {
704 for item in v {
705 res.push(DatastoreAdministratorInformationEntry {
706 node_id: item.get_int(&[1]),
707 friendly_name: item.get_string_owned(&[2]),
708 vendor_id: item.get_int(&[3]).map(|v| v as u16),
709 icac: item.get_octet_string_owned(&[4]),
710 });
711 }
712 }
713 Ok(res)
714}
715
716pub fn decode_status(inp: &tlv::TlvItemValue) -> anyhow::Result<DatastoreStatusEntry> {
718 if let tlv::TlvItemValue::List(_fields) = inp {
719 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
721 Ok(DatastoreStatusEntry {
722 state: item.get_int(&[0]).and_then(|v| DatastoreState::from_u8(v as u8)),
723 update_timestamp: item.get_int(&[1]),
724 failure_code: item.get_int(&[2]).map(|v| v as u8),
725 })
726 } else {
727 Err(anyhow::anyhow!("Expected struct fields"))
728 }
729}
730
731pub fn decode_endpoint_group_id_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreEndpointGroupIDEntry>> {
733 let mut res = Vec::new();
734 if let tlv::TlvItemValue::List(v) = inp {
735 for item in v {
736 res.push(DatastoreEndpointGroupIDEntry {
737 node_id: item.get_int(&[0]),
738 endpoint_id: item.get_int(&[1]).map(|v| v as u16),
739 group_id: item.get_int(&[2]).map(|v| v as u8),
740 status_entry: {
741 if let Some(nested_tlv) = item.get(&[3]) {
742 if let tlv::TlvItemValue::List(_) = nested_tlv {
743 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
744 Some(DatastoreStatusEntry {
745 state: nested_item.get_int(&[0]).and_then(|v| DatastoreState::from_u8(v as u8)),
746 update_timestamp: nested_item.get_int(&[1]),
747 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
748 })
749 } else {
750 None
751 }
752 } else {
753 None
754 }
755 },
756 });
757 }
758 }
759 Ok(res)
760}
761
762pub fn decode_endpoint_binding_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreEndpointBindingEntry>> {
764 let mut res = Vec::new();
765 if let tlv::TlvItemValue::List(v) = inp {
766 for item in v {
767 res.push(DatastoreEndpointBindingEntry {
768 node_id: item.get_int(&[0]),
769 endpoint_id: item.get_int(&[1]).map(|v| v as u16),
770 list_id: item.get_int(&[2]).map(|v| v as u16),
771 binding: {
772 if let Some(nested_tlv) = item.get(&[3]) {
773 if let tlv::TlvItemValue::List(_) = nested_tlv {
774 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
775 Some(DatastoreBindingTarget {
776 node: nested_item.get_int(&[1]),
777 group: nested_item.get_int(&[2]).map(|v| v as u8),
778 endpoint: nested_item.get_int(&[3]).map(|v| v as u16),
779 cluster: nested_item.get_int(&[4]).map(|v| v as u32),
780 })
781 } else {
782 None
783 }
784 } else {
785 None
786 }
787 },
788 status_entry: {
789 if let Some(nested_tlv) = item.get(&[4]) {
790 if let tlv::TlvItemValue::List(_) = nested_tlv {
791 let nested_item = tlv::TlvItem { tag: 4, value: nested_tlv.clone() };
792 Some(DatastoreStatusEntry {
793 state: nested_item.get_int(&[0]).and_then(|v| DatastoreState::from_u8(v as u8)),
794 update_timestamp: nested_item.get_int(&[1]),
795 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
796 })
797 } else {
798 None
799 }
800 } else {
801 None
802 }
803 },
804 });
805 }
806 }
807 Ok(res)
808}
809
810pub fn decode_node_key_set_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreNodeKeySetEntry>> {
812 let mut res = Vec::new();
813 if let tlv::TlvItemValue::List(v) = inp {
814 for item in v {
815 res.push(DatastoreNodeKeySetEntry {
816 node_id: item.get_int(&[0]),
817 group_key_set_id: item.get_int(&[1]).map(|v| v as u16),
818 status_entry: {
819 if let Some(nested_tlv) = item.get(&[2]) {
820 if let tlv::TlvItemValue::List(_) = nested_tlv {
821 let nested_item = tlv::TlvItem { tag: 2, value: nested_tlv.clone() };
822 Some(DatastoreStatusEntry {
823 state: nested_item.get_int(&[0]).and_then(|v| DatastoreState::from_u8(v as u8)),
824 update_timestamp: nested_item.get_int(&[1]),
825 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
826 })
827 } else {
828 None
829 }
830 } else {
831 None
832 }
833 },
834 });
835 }
836 }
837 Ok(res)
838}
839
840pub fn decode_node_acl_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreACLEntry>> {
842 let mut res = Vec::new();
843 if let tlv::TlvItemValue::List(v) = inp {
844 for item in v {
845 res.push(DatastoreACLEntry {
846 node_id: item.get_int(&[0]),
847 list_id: item.get_int(&[1]).map(|v| v as u16),
848 acl_entry: {
849 if let Some(nested_tlv) = item.get(&[2]) {
850 if let tlv::TlvItemValue::List(_) = nested_tlv {
851 let nested_item = tlv::TlvItem { tag: 2, value: nested_tlv.clone() };
852 Some(DatastoreAccessControlEntry {
853 privilege: nested_item.get_int(&[1]).and_then(|v| DatastoreAccessControlEntryPrivilege::from_u8(v as u8)),
854 auth_mode: nested_item.get_int(&[2]).and_then(|v| DatastoreAccessControlEntryAuthMode::from_u8(v as u8)),
855 subjects: {
856 if let Some(tlv::TlvItemValue::List(l)) = nested_item.get(&[3]) {
857 let items: Vec<u64> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v) } else { None } }).collect();
858 Some(items)
859 } else {
860 None
861 }
862 },
863 targets: {
864 if let Some(tlv::TlvItemValue::List(l)) = nested_item.get(&[4]) {
865 let mut items = Vec::new();
866 for list_item in l {
867 items.push(DatastoreAccessControlTarget {
868 cluster: list_item.get_int(&[0]).map(|v| v as u32),
869 endpoint: list_item.get_int(&[1]).map(|v| v as u16),
870 device_type: list_item.get_int(&[2]).map(|v| v as u32),
871 });
872 }
873 Some(items)
874 } else {
875 None
876 }
877 },
878 })
879 } else {
880 None
881 }
882 } else {
883 None
884 }
885 },
886 status_entry: {
887 if let Some(nested_tlv) = item.get(&[3]) {
888 if let tlv::TlvItemValue::List(_) = nested_tlv {
889 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
890 Some(DatastoreStatusEntry {
891 state: nested_item.get_int(&[0]).and_then(|v| DatastoreState::from_u8(v as u8)),
892 update_timestamp: nested_item.get_int(&[1]),
893 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
894 })
895 } else {
896 None
897 }
898 } else {
899 None
900 }
901 },
902 });
903 }
904 }
905 Ok(res)
906}
907
908pub fn decode_node_endpoint_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<DatastoreEndpointEntry>> {
910 let mut res = Vec::new();
911 if let tlv::TlvItemValue::List(v) = inp {
912 for item in v {
913 res.push(DatastoreEndpointEntry {
914 endpoint_id: item.get_int(&[0]).map(|v| v as u16),
915 node_id: item.get_int(&[1]),
916 friendly_name: item.get_string_owned(&[2]),
917 status_entry: {
918 if let Some(nested_tlv) = item.get(&[3]) {
919 if let tlv::TlvItemValue::List(_) = nested_tlv {
920 let nested_item = tlv::TlvItem { tag: 3, value: nested_tlv.clone() };
921 Some(DatastoreStatusEntry {
922 state: nested_item.get_int(&[0]).and_then(|v| DatastoreState::from_u8(v as u8)),
923 update_timestamp: nested_item.get_int(&[1]),
924 failure_code: nested_item.get_int(&[2]).map(|v| v as u8),
925 })
926 } else {
927 None
928 }
929 } else {
930 None
931 }
932 },
933 });
934 }
935 }
936 Ok(res)
937}
938
939
940pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
952 if cluster_id != 0x0752 {
954 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0752, got {}\"}}", cluster_id);
955 }
956
957 match attribute_id {
958 0x0000 => {
959 match decode_anchor_root_ca(tlv_value) {
960 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
961 Err(e) => format!("{{\"error\": \"{}\"}}", e),
962 }
963 }
964 0x0001 => {
965 match decode_anchor_node_id(tlv_value) {
966 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
967 Err(e) => format!("{{\"error\": \"{}\"}}", e),
968 }
969 }
970 0x0002 => {
971 match decode_anchor_vendor_id(tlv_value) {
972 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
973 Err(e) => format!("{{\"error\": \"{}\"}}", e),
974 }
975 }
976 0x0003 => {
977 match decode_friendly_name(tlv_value) {
978 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
979 Err(e) => format!("{{\"error\": \"{}\"}}", e),
980 }
981 }
982 0x0004 => {
983 match decode_group_key_set_list(tlv_value) {
984 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
985 Err(e) => format!("{{\"error\": \"{}\"}}", e),
986 }
987 }
988 0x0005 => {
989 match decode_group_list(tlv_value) {
990 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
991 Err(e) => format!("{{\"error\": \"{}\"}}", e),
992 }
993 }
994 0x0006 => {
995 match decode_node_list(tlv_value) {
996 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
997 Err(e) => format!("{{\"error\": \"{}\"}}", e),
998 }
999 }
1000 0x0007 => {
1001 match decode_admin_list(tlv_value) {
1002 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1003 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1004 }
1005 }
1006 0x0008 => {
1007 match decode_status(tlv_value) {
1008 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1009 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1010 }
1011 }
1012 0x0009 => {
1013 match decode_endpoint_group_id_list(tlv_value) {
1014 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1015 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1016 }
1017 }
1018 0x000A => {
1019 match decode_endpoint_binding_list(tlv_value) {
1020 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1021 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1022 }
1023 }
1024 0x000B => {
1025 match decode_node_key_set_list(tlv_value) {
1026 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1027 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1028 }
1029 }
1030 0x000C => {
1031 match decode_node_acl_list(tlv_value) {
1032 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1033 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1034 }
1035 }
1036 0x000D => {
1037 match decode_node_endpoint_list(tlv_value) {
1038 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1039 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1040 }
1041 }
1042 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1043 }
1044}
1045
1046pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1051 vec![
1052 (0x0000, "AnchorRootCA"),
1053 (0x0001, "AnchorNodeID"),
1054 (0x0002, "AnchorVendorID"),
1055 (0x0003, "FriendlyName"),
1056 (0x0004, "GroupKeySetList"),
1057 (0x0005, "GroupList"),
1058 (0x0006, "NodeList"),
1059 (0x0007, "AdminList"),
1060 (0x0008, "Status"),
1061 (0x0009, "EndpointGroupIDList"),
1062 (0x000A, "EndpointBindingList"),
1063 (0x000B, "NodeKeySetList"),
1064 (0x000C, "NodeACLList"),
1065 (0x000D, "NodeEndpointList"),
1066 ]
1067}
1068