matc/clusters/codec/
thread_border_router_management.rs

1//! Matter TLV encoders and decoders for Thread Border Router Management Cluster
2//! Cluster ID: 0x0452
3//!
4//! This file is automatically generated from ThreadBorderRouterManagement.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Import serialization helpers for octet strings
12use crate::clusters::helpers::{serialize_opt_bytes_as_hex};
13
14// Command encoders
15
16/// Encode SetActiveDatasetRequest command (0x03)
17pub 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
28/// Encode SetPendingDatasetRequest command (0x04)
29pub 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
39// Attribute decoders
40
41/// Decode BorderRouterName attribute (0x0000)
42pub 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
50/// Decode BorderAgentID attribute (0x0001)
51pub 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
59/// Decode ThreadVersion attribute (0x0002)
60pub 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
68/// Decode InterfaceEnabled attribute (0x0003)
69pub 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
77/// Decode ActiveDatasetTimestamp attribute (0x0004)
78pub 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
86/// Decode PendingDatasetTimestamp attribute (0x0005)
87pub 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
96// JSON dispatcher function
97
98/// Decode attribute value and return as JSON string
99///
100/// # Parameters
101/// * `cluster_id` - The cluster identifier
102/// * `attribute_id` - The attribute identifier
103/// * `tlv_value` - The TLV value to decode
104///
105/// # Returns
106/// JSON string representation of the decoded value or error
107pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
108    // Verify this is the correct cluster
109    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
154/// Get list of all attributes supported by this cluster
155///
156/// # Returns
157/// Vector of tuples containing (attribute_id, attribute_name)
158pub 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
175// Command response decoders
176
177/// Decode DatasetResponse command response (02)
178pub 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