matc/clusters/codec/
thread_network_directory.rs1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, serde::Serialize)]
14pub struct ThreadNetwork {
15 pub extended_pan_id: Option<Vec<u8>>,
16 pub network_name: Option<String>,
17 pub channel: Option<u16>,
18 pub active_timestamp: Option<u64>,
19}
20
21pub fn encode_add_network(operational_dataset: Vec<u8>) -> anyhow::Result<Vec<u8>> {
25 let tlv = tlv::TlvItemEnc {
26 tag: 0,
27 value: tlv::TlvItemValueEnc::StructInvisible(vec![
28 (0, tlv::TlvItemValueEnc::OctetString(operational_dataset)).into(),
29 ]),
30 };
31 Ok(tlv.encode()?)
32}
33
34pub fn encode_remove_network(extended_pan_id: Vec<u8>) -> anyhow::Result<Vec<u8>> {
36 let tlv = tlv::TlvItemEnc {
37 tag: 0,
38 value: tlv::TlvItemValueEnc::StructInvisible(vec![
39 (0, tlv::TlvItemValueEnc::OctetString(extended_pan_id)).into(),
40 ]),
41 };
42 Ok(tlv.encode()?)
43}
44
45pub fn encode_get_operational_dataset(extended_pan_id: Vec<u8>) -> anyhow::Result<Vec<u8>> {
47 let tlv = tlv::TlvItemEnc {
48 tag: 0,
49 value: tlv::TlvItemValueEnc::StructInvisible(vec![
50 (0, tlv::TlvItemValueEnc::OctetString(extended_pan_id)).into(),
51 ]),
52 };
53 Ok(tlv.encode()?)
54}
55
56pub fn decode_preferred_extended_pan_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
60 if let tlv::TlvItemValue::OctetString(v) = inp {
61 Ok(Some(v.clone()))
62 } else {
63 Ok(None)
64 }
65}
66
67pub fn decode_thread_networks(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<ThreadNetwork>> {
69 let mut res = Vec::new();
70 if let tlv::TlvItemValue::List(v) = inp {
71 for item in v {
72 res.push(ThreadNetwork {
73 extended_pan_id: item.get_octet_string_owned(&[0]),
74 network_name: item.get_string_owned(&[1]),
75 channel: item.get_int(&[2]).map(|v| v as u16),
76 active_timestamp: item.get_int(&[3]),
77 });
78 }
79 }
80 Ok(res)
81}
82
83pub fn decode_thread_network_table_size(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
85 if let tlv::TlvItemValue::Int(v) = inp {
86 Ok(*v as u8)
87 } else {
88 Err(anyhow::anyhow!("Expected Integer"))
89 }
90}
91
92
93pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
105 if cluster_id != 0x0453 {
107 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0453, got {}\"}}", cluster_id);
108 }
109
110 match attribute_id {
111 0x0000 => {
112 match decode_preferred_extended_pan_id(tlv_value) {
113 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
114 Err(e) => format!("{{\"error\": \"{}\"}}", e),
115 }
116 }
117 0x0001 => {
118 match decode_thread_networks(tlv_value) {
119 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
120 Err(e) => format!("{{\"error\": \"{}\"}}", e),
121 }
122 }
123 0x0002 => {
124 match decode_thread_network_table_size(tlv_value) {
125 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
126 Err(e) => format!("{{\"error\": \"{}\"}}", e),
127 }
128 }
129 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
130 }
131}
132
133pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
138 vec![
139 (0x0000, "PreferredExtendedPanID"),
140 (0x0001, "ThreadNetworks"),
141 (0x0002, "ThreadNetworkTableSize"),
142 ]
143}
144