matc/clusters/codec/
icd_management.rs

1//! Generated Matter TLV encoders and decoders for ICD Management Cluster
2//! Cluster ID: 0x0046
3//! 
4//! This file is automatically generated from ICDManagement.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct MonitoringRegistration {
15    pub check_in_node_id: Option<u64>,
16    pub monitored_subject: Option<u64>,
17    pub key: Option<u8>,
18    pub client_type: Option<u8>,
19}
20
21// Command encoders
22
23/// Encode RegisterClient command (0x00)
24pub fn encode_register_client(check_in_node_id: u64, monitored_subject: u64, key: Vec<u8>, verification_key: Vec<u8>, client_type: u8) -> anyhow::Result<Vec<u8>> {
25    let tlv = tlv::TlvItemEnc {
26        tag: 0,
27        value: tlv::TlvItemValueEnc::StructInvisible(vec![
28        (0, tlv::TlvItemValueEnc::UInt64(check_in_node_id)).into(),
29        (1, tlv::TlvItemValueEnc::UInt64(monitored_subject)).into(),
30        (2, tlv::TlvItemValueEnc::OctetString(key)).into(),
31        (3, tlv::TlvItemValueEnc::OctetString(verification_key)).into(),
32        (4, tlv::TlvItemValueEnc::UInt8(client_type)).into(),
33        ]),
34    };
35    Ok(tlv.encode()?)
36}
37
38/// Encode UnregisterClient command (0x02)
39pub fn encode_unregister_client(check_in_node_id: u64, verification_key: Vec<u8>) -> anyhow::Result<Vec<u8>> {
40    let tlv = tlv::TlvItemEnc {
41        tag: 0,
42        value: tlv::TlvItemValueEnc::StructInvisible(vec![
43        (0, tlv::TlvItemValueEnc::UInt64(check_in_node_id)).into(),
44        (1, tlv::TlvItemValueEnc::OctetString(verification_key)).into(),
45        ]),
46    };
47    Ok(tlv.encode()?)
48}
49
50/// Encode StayActiveRequest command (0x03)
51pub fn encode_stay_active_request(stay_active_duration: u32) -> anyhow::Result<Vec<u8>> {
52    let tlv = tlv::TlvItemEnc {
53        tag: 0,
54        value: tlv::TlvItemValueEnc::StructInvisible(vec![
55        (0, tlv::TlvItemValueEnc::UInt32(stay_active_duration)).into(),
56        ]),
57    };
58    Ok(tlv.encode()?)
59}
60
61// Attribute decoders
62
63/// Decode IdleModeDuration attribute (0x0000)
64pub fn decode_idle_mode_duration(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
65    if let tlv::TlvItemValue::Int(v) = inp {
66        Ok(*v as u32)
67    } else {
68        Err(anyhow::anyhow!("Expected Integer"))
69    }
70}
71
72/// Decode ActiveModeDuration attribute (0x0001)
73pub fn decode_active_mode_duration(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
74    if let tlv::TlvItemValue::Int(v) = inp {
75        Ok(*v as u32)
76    } else {
77        Err(anyhow::anyhow!("Expected Integer"))
78    }
79}
80
81/// Decode ActiveModeThreshold attribute (0x0002)
82pub fn decode_active_mode_threshold(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
83    if let tlv::TlvItemValue::Int(v) = inp {
84        Ok(*v as u16)
85    } else {
86        Err(anyhow::anyhow!("Expected Integer"))
87    }
88}
89
90/// Decode RegisteredClients attribute (0x0003)
91pub fn decode_registered_clients(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<MonitoringRegistration>> {
92    let mut res = Vec::new();
93    if let tlv::TlvItemValue::List(v) = inp {
94        for item in v {
95            res.push(MonitoringRegistration {
96                check_in_node_id: item.get_int(&[1]),
97                monitored_subject: item.get_int(&[2]),
98                key: item.get_int(&[3]).map(|v| v as u8),
99                client_type: item.get_int(&[4]).map(|v| v as u8),
100            });
101        }
102    }
103    Ok(res)
104}
105
106/// Decode ICDCounter attribute (0x0004)
107pub fn decode_icd_counter(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
108    if let tlv::TlvItemValue::Int(v) = inp {
109        Ok(*v as u32)
110    } else {
111        Err(anyhow::anyhow!("Expected Integer"))
112    }
113}
114
115/// Decode ClientsSupportedPerFabric attribute (0x0005)
116pub fn decode_clients_supported_per_fabric(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
117    if let tlv::TlvItemValue::Int(v) = inp {
118        Ok(*v as u16)
119    } else {
120        Err(anyhow::anyhow!("Expected Integer"))
121    }
122}
123
124/// Decode UserActiveModeTriggerHint attribute (0x0006)
125pub fn decode_user_active_mode_trigger_hint(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
126    if let tlv::TlvItemValue::Int(v) = inp {
127        Ok(*v as u8)
128    } else {
129        Err(anyhow::anyhow!("Expected Integer"))
130    }
131}
132
133/// Decode UserActiveModeTriggerInstruction attribute (0x0007)
134pub fn decode_user_active_mode_trigger_instruction(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
135    if let tlv::TlvItemValue::String(v) = inp {
136        Ok(v.clone())
137    } else {
138        Err(anyhow::anyhow!("Expected String"))
139    }
140}
141
142/// Decode OperatingMode attribute (0x0008)
143pub fn decode_operating_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
144    if let tlv::TlvItemValue::Int(v) = inp {
145        Ok(*v as u8)
146    } else {
147        Err(anyhow::anyhow!("Expected Integer"))
148    }
149}
150
151/// Decode MaximumCheckInBackoff attribute (0x0009)
152pub fn decode_maximum_check_in_backoff(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
153    if let tlv::TlvItemValue::Int(v) = inp {
154        Ok(*v as u32)
155    } else {
156        Err(anyhow::anyhow!("Expected Integer"))
157    }
158}
159
160
161// JSON dispatcher function
162
163/// Decode attribute value and return as JSON string
164/// 
165/// # Parameters
166/// * `cluster_id` - The cluster identifier
167/// * `attribute_id` - The attribute identifier
168/// * `tlv_value` - The TLV value to decode
169/// 
170/// # Returns
171/// JSON string representation of the decoded value or error
172pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
173    // Verify this is the correct cluster
174    if cluster_id != 0x0046 {
175        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0046, got {}\"}}", cluster_id);
176    }
177    
178    match attribute_id {
179        0x0000 => {
180            match decode_idle_mode_duration(tlv_value) {
181                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
182                Err(e) => format!("{{\"error\": \"{}\"}}", e),
183            }
184        }
185        0x0001 => {
186            match decode_active_mode_duration(tlv_value) {
187                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
188                Err(e) => format!("{{\"error\": \"{}\"}}", e),
189            }
190        }
191        0x0002 => {
192            match decode_active_mode_threshold(tlv_value) {
193                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
194                Err(e) => format!("{{\"error\": \"{}\"}}", e),
195            }
196        }
197        0x0003 => {
198            match decode_registered_clients(tlv_value) {
199                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
200                Err(e) => format!("{{\"error\": \"{}\"}}", e),
201            }
202        }
203        0x0004 => {
204            match decode_icd_counter(tlv_value) {
205                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
206                Err(e) => format!("{{\"error\": \"{}\"}}", e),
207            }
208        }
209        0x0005 => {
210            match decode_clients_supported_per_fabric(tlv_value) {
211                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
212                Err(e) => format!("{{\"error\": \"{}\"}}", e),
213            }
214        }
215        0x0006 => {
216            match decode_user_active_mode_trigger_hint(tlv_value) {
217                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
218                Err(e) => format!("{{\"error\": \"{}\"}}", e),
219            }
220        }
221        0x0007 => {
222            match decode_user_active_mode_trigger_instruction(tlv_value) {
223                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
224                Err(e) => format!("{{\"error\": \"{}\"}}", e),
225            }
226        }
227        0x0008 => {
228            match decode_operating_mode(tlv_value) {
229                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
230                Err(e) => format!("{{\"error\": \"{}\"}}", e),
231            }
232        }
233        0x0009 => {
234            match decode_maximum_check_in_backoff(tlv_value) {
235                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
236                Err(e) => format!("{{\"error\": \"{}\"}}", e),
237            }
238        }
239        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
240    }
241}
242
243/// Get list of all attributes supported by this cluster
244/// 
245/// # Returns
246/// Vector of tuples containing (attribute_id, attribute_name)
247pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
248    vec![
249        (0x0000, "IdleModeDuration"),
250        (0x0001, "ActiveModeDuration"),
251        (0x0002, "ActiveModeThreshold"),
252        (0x0003, "RegisteredClients"),
253        (0x0004, "ICDCounter"),
254        (0x0005, "ClientsSupportedPerFabric"),
255        (0x0006, "UserActiveModeTriggerHint"),
256        (0x0007, "UserActiveModeTriggerInstruction"),
257        (0x0008, "OperatingMode"),
258        (0x0009, "MaximumCheckInBackoff"),
259    ]
260}
261