matc/clusters/codec/
thread_border_router_management.rs1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11use crate::clusters::helpers::{serialize_opt_bytes_as_hex};
13
14pub fn encode_set_active_dataset_request(active_dataset: Vec<u8>, breadcrumb: u64) -> anyhow::Result<Vec<u8>> {
18 let tlv = tlv::TlvItemEnc {
19 tag: 0,
20 value: tlv::TlvItemValueEnc::StructInvisible(vec![
21 (0, tlv::TlvItemValueEnc::OctetString(active_dataset)).into(),
22 (1, tlv::TlvItemValueEnc::UInt64(breadcrumb)).into(),
23 ]),
24 };
25 Ok(tlv.encode()?)
26}
27
28pub fn encode_set_pending_dataset_request(pending_dataset: Vec<u8>) -> anyhow::Result<Vec<u8>> {
30 let tlv = tlv::TlvItemEnc {
31 tag: 0,
32 value: tlv::TlvItemValueEnc::StructInvisible(vec![
33 (0, tlv::TlvItemValueEnc::OctetString(pending_dataset)).into(),
34 ]),
35 };
36 Ok(tlv.encode()?)
37}
38
39pub fn decode_border_router_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
43 if let tlv::TlvItemValue::String(v) = inp {
44 Ok(v.clone())
45 } else {
46 Err(anyhow::anyhow!("Expected String"))
47 }
48}
49
50pub fn decode_border_agent_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
52 if let tlv::TlvItemValue::OctetString(v) = inp {
53 Ok(v.clone())
54 } else {
55 Err(anyhow::anyhow!("Expected OctetString"))
56 }
57}
58
59pub fn decode_thread_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
61 if let tlv::TlvItemValue::Int(v) = inp {
62 Ok(*v as u16)
63 } else {
64 Err(anyhow::anyhow!("Expected UInt16"))
65 }
66}
67
68pub fn decode_interface_enabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
70 if let tlv::TlvItemValue::Bool(v) = inp {
71 Ok(*v)
72 } else {
73 Err(anyhow::anyhow!("Expected Bool"))
74 }
75}
76
77pub fn decode_active_dataset_timestamp(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
79 if let tlv::TlvItemValue::Int(v) = inp {
80 Ok(Some(*v))
81 } else {
82 Ok(None)
83 }
84}
85
86pub fn decode_pending_dataset_timestamp(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
88 if let tlv::TlvItemValue::Int(v) = inp {
89 Ok(Some(*v))
90 } else {
91 Ok(None)
92 }
93}
94
95
96pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
108 if cluster_id != 0x0452 {
110 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0452, got {}\"}}", cluster_id);
111 }
112
113 match attribute_id {
114 0x0000 => {
115 match decode_border_router_name(tlv_value) {
116 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
117 Err(e) => format!("{{\"error\": \"{}\"}}", e),
118 }
119 }
120 0x0001 => {
121 match decode_border_agent_id(tlv_value) {
122 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
123 Err(e) => format!("{{\"error\": \"{}\"}}", e),
124 }
125 }
126 0x0002 => {
127 match decode_thread_version(tlv_value) {
128 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
129 Err(e) => format!("{{\"error\": \"{}\"}}", e),
130 }
131 }
132 0x0003 => {
133 match decode_interface_enabled(tlv_value) {
134 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
135 Err(e) => format!("{{\"error\": \"{}\"}}", e),
136 }
137 }
138 0x0004 => {
139 match decode_active_dataset_timestamp(tlv_value) {
140 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
141 Err(e) => format!("{{\"error\": \"{}\"}}", e),
142 }
143 }
144 0x0005 => {
145 match decode_pending_dataset_timestamp(tlv_value) {
146 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
147 Err(e) => format!("{{\"error\": \"{}\"}}", e),
148 }
149 }
150 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
151 }
152}
153
154pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
159 vec![
160 (0x0000, "BorderRouterName"),
161 (0x0001, "BorderAgentID"),
162 (0x0002, "ThreadVersion"),
163 (0x0003, "InterfaceEnabled"),
164 (0x0004, "ActiveDatasetTimestamp"),
165 (0x0005, "PendingDatasetTimestamp"),
166 ]
167}
168
169#[derive(Debug, serde::Serialize)]
170pub struct DatasetResponse {
171 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
172 pub dataset: Option<Vec<u8>>,
173}
174
175pub fn decode_dataset_response(inp: &tlv::TlvItemValue) -> anyhow::Result<DatasetResponse> {
179 if let tlv::TlvItemValue::List(_fields) = inp {
180 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
181 Ok(DatasetResponse {
182 dataset: item.get_octet_string_owned(&[0]),
183 })
184 } else {
185 Err(anyhow::anyhow!("Expected struct fields"))
186 }
187}
188