matc/clusters/codec/
bridged_device_basic_information_cluster.rs

1//! Generated Matter TLV encoders and decoders for Bridged Device Basic Information Cluster
2//! Cluster ID: 0x0039
3//! 
4//! This file is automatically generated from BridgedDeviceBasicInformationCluster.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct CapabilityMinima {
15    pub case_sessions_per_fabric: Option<u16>,
16    pub subscriptions_per_fabric: Option<u16>,
17}
18
19#[derive(Debug, serde::Serialize)]
20pub struct ProductAppearance {
21    pub finish: Option<u8>,
22    pub primary_color: Option<u8>,
23}
24
25// Command encoders
26
27/// Encode KeepActive command (0x80)
28pub fn encode_keep_active(stay_active_duration: u32, timeout_ms: u32) -> anyhow::Result<Vec<u8>> {
29    let tlv = tlv::TlvItemEnc {
30        tag: 0,
31        value: tlv::TlvItemValueEnc::StructInvisible(vec![
32        (0, tlv::TlvItemValueEnc::UInt32(stay_active_duration)).into(),
33        (1, tlv::TlvItemValueEnc::UInt32(timeout_ms)).into(),
34        ]),
35    };
36    Ok(tlv.encode()?)
37}
38
39// Attribute decoders
40
41/// Decode DataModelRevision attribute (0x0000)
42pub fn decode_data_model_revision(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
43    if let tlv::TlvItemValue::Int(v) = inp {
44        Ok(*v as u16)
45    } else {
46        Err(anyhow::anyhow!("Expected Integer"))
47    }
48}
49
50/// Decode VendorName attribute (0x0001)
51pub fn decode_vendor_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
52    if let tlv::TlvItemValue::String(v) = inp {
53        Ok(v.clone())
54    } else {
55        Err(anyhow::anyhow!("Expected String"))
56    }
57}
58
59/// Decode VendorID attribute (0x0002)
60pub fn decode_vendor_id(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 Integer"))
65    }
66}
67
68/// Decode ProductName attribute (0x0003)
69pub fn decode_product_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
70    if let tlv::TlvItemValue::String(v) = inp {
71        Ok(v.clone())
72    } else {
73        Err(anyhow::anyhow!("Expected String"))
74    }
75}
76
77/// Decode ProductID attribute (0x0004)
78pub fn decode_product_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
79    if let tlv::TlvItemValue::Int(v) = inp {
80        Ok(*v as u16)
81    } else {
82        Err(anyhow::anyhow!("Expected Integer"))
83    }
84}
85
86/// Decode NodeLabel attribute (0x0005)
87pub fn decode_node_label(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
88    if let tlv::TlvItemValue::String(v) = inp {
89        Ok(v.clone())
90    } else {
91        Err(anyhow::anyhow!("Expected String"))
92    }
93}
94
95/// Decode Location attribute (0x0006)
96pub fn decode_location(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
97    if let tlv::TlvItemValue::String(v) = inp {
98        Ok(v.clone())
99    } else {
100        Err(anyhow::anyhow!("Expected String"))
101    }
102}
103
104/// Decode HardwareVersion attribute (0x0007)
105pub fn decode_hardware_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
106    if let tlv::TlvItemValue::Int(v) = inp {
107        Ok(*v as u16)
108    } else {
109        Err(anyhow::anyhow!("Expected Integer"))
110    }
111}
112
113/// Decode HardwareVersionString attribute (0x0008)
114pub fn decode_hardware_version_string(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
115    if let tlv::TlvItemValue::String(v) = inp {
116        Ok(v.clone())
117    } else {
118        Err(anyhow::anyhow!("Expected String"))
119    }
120}
121
122/// Decode SoftwareVersion attribute (0x0009)
123pub fn decode_software_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
124    if let tlv::TlvItemValue::Int(v) = inp {
125        Ok(*v as u32)
126    } else {
127        Err(anyhow::anyhow!("Expected Integer"))
128    }
129}
130
131/// Decode SoftwareVersionString attribute (0x000A)
132pub fn decode_software_version_string(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
133    if let tlv::TlvItemValue::String(v) = inp {
134        Ok(v.clone())
135    } else {
136        Err(anyhow::anyhow!("Expected String"))
137    }
138}
139
140/// Decode ManufacturingDate attribute (0x000B)
141pub fn decode_manufacturing_date(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
142    if let tlv::TlvItemValue::String(v) = inp {
143        Ok(v.clone())
144    } else {
145        Err(anyhow::anyhow!("Expected String"))
146    }
147}
148
149/// Decode PartNumber attribute (0x000C)
150pub fn decode_part_number(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
151    if let tlv::TlvItemValue::String(v) = inp {
152        Ok(v.clone())
153    } else {
154        Err(anyhow::anyhow!("Expected String"))
155    }
156}
157
158/// Decode ProductURL attribute (0x000D)
159pub fn decode_product_url(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
160    if let tlv::TlvItemValue::String(v) = inp {
161        Ok(v.clone())
162    } else {
163        Err(anyhow::anyhow!("Expected String"))
164    }
165}
166
167/// Decode ProductLabel attribute (0x000E)
168pub fn decode_product_label(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
169    if let tlv::TlvItemValue::String(v) = inp {
170        Ok(v.clone())
171    } else {
172        Err(anyhow::anyhow!("Expected String"))
173    }
174}
175
176/// Decode SerialNumber attribute (0x000F)
177pub fn decode_serial_number(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
178    if let tlv::TlvItemValue::String(v) = inp {
179        Ok(v.clone())
180    } else {
181        Err(anyhow::anyhow!("Expected String"))
182    }
183}
184
185/// Decode LocalConfigDisabled attribute (0x0010)
186pub fn decode_local_config_disabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
187    if let tlv::TlvItemValue::Bool(v) = inp {
188        Ok(*v)
189    } else {
190        Err(anyhow::anyhow!("Expected Bool"))
191    }
192}
193
194/// Decode Reachable attribute (0x0011)
195pub fn decode_reachable(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
196    if let tlv::TlvItemValue::Bool(v) = inp {
197        Ok(*v)
198    } else {
199        Err(anyhow::anyhow!("Expected Bool"))
200    }
201}
202
203/// Decode UniqueID attribute (0x0012)
204pub fn decode_unique_id(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
205    if let tlv::TlvItemValue::String(v) = inp {
206        Ok(v.clone())
207    } else {
208        Err(anyhow::anyhow!("Expected String"))
209    }
210}
211
212/// Decode CapabilityMinima attribute (0x0013)
213pub fn decode_capability_minima(inp: &tlv::TlvItemValue) -> anyhow::Result<CapabilityMinima> {
214    if let tlv::TlvItemValue::List(_fields) = inp {
215        // Struct with fields
216        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
217        Ok(CapabilityMinima {
218                case_sessions_per_fabric: item.get_int(&[0]).map(|v| v as u16),
219                subscriptions_per_fabric: item.get_int(&[1]).map(|v| v as u16),
220        })
221    } else {
222        Err(anyhow::anyhow!("Expected struct fields"))
223    }
224}
225
226/// Decode ProductAppearance attribute (0x0014)
227pub fn decode_product_appearance(inp: &tlv::TlvItemValue) -> anyhow::Result<ProductAppearance> {
228    if let tlv::TlvItemValue::List(_fields) = inp {
229        // Struct with fields
230        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
231        Ok(ProductAppearance {
232                finish: item.get_int(&[0]).map(|v| v as u8),
233                primary_color: item.get_int(&[1]).map(|v| v as u8),
234        })
235    } else {
236        Err(anyhow::anyhow!("Expected struct fields"))
237    }
238}
239
240/// Decode SpecificationVersion attribute (0x0015)
241pub fn decode_specification_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
242    if let tlv::TlvItemValue::Int(v) = inp {
243        Ok(*v as u32)
244    } else {
245        Err(anyhow::anyhow!("Expected Integer"))
246    }
247}
248
249/// Decode MaxPathsPerInvoke attribute (0x0016)
250pub fn decode_max_paths_per_invoke(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
251    if let tlv::TlvItemValue::Int(v) = inp {
252        Ok(*v as u16)
253    } else {
254        Err(anyhow::anyhow!("Expected Integer"))
255    }
256}
257
258/// Decode ConfigurationVersion attribute (0x0018)
259pub fn decode_configuration_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
260    if let tlv::TlvItemValue::Int(v) = inp {
261        Ok(*v as u32)
262    } else {
263        Err(anyhow::anyhow!("Expected Integer"))
264    }
265}
266
267
268// JSON dispatcher function
269
270/// Decode attribute value and return as JSON string
271/// 
272/// # Parameters
273/// * `cluster_id` - The cluster identifier
274/// * `attribute_id` - The attribute identifier
275/// * `tlv_value` - The TLV value to decode
276/// 
277/// # Returns
278/// JSON string representation of the decoded value or error
279pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
280    // Verify this is the correct cluster
281    if cluster_id != 0x0039 {
282        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0039, got {}\"}}", cluster_id);
283    }
284    
285    match attribute_id {
286        0x0000 => {
287            match decode_data_model_revision(tlv_value) {
288                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
289                Err(e) => format!("{{\"error\": \"{}\"}}", e),
290            }
291        }
292        0x0001 => {
293            match decode_vendor_name(tlv_value) {
294                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
295                Err(e) => format!("{{\"error\": \"{}\"}}", e),
296            }
297        }
298        0x0002 => {
299            match decode_vendor_id(tlv_value) {
300                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
301                Err(e) => format!("{{\"error\": \"{}\"}}", e),
302            }
303        }
304        0x0003 => {
305            match decode_product_name(tlv_value) {
306                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
307                Err(e) => format!("{{\"error\": \"{}\"}}", e),
308            }
309        }
310        0x0004 => {
311            match decode_product_id(tlv_value) {
312                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
313                Err(e) => format!("{{\"error\": \"{}\"}}", e),
314            }
315        }
316        0x0005 => {
317            match decode_node_label(tlv_value) {
318                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
319                Err(e) => format!("{{\"error\": \"{}\"}}", e),
320            }
321        }
322        0x0006 => {
323            match decode_location(tlv_value) {
324                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
325                Err(e) => format!("{{\"error\": \"{}\"}}", e),
326            }
327        }
328        0x0007 => {
329            match decode_hardware_version(tlv_value) {
330                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
331                Err(e) => format!("{{\"error\": \"{}\"}}", e),
332            }
333        }
334        0x0008 => {
335            match decode_hardware_version_string(tlv_value) {
336                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
337                Err(e) => format!("{{\"error\": \"{}\"}}", e),
338            }
339        }
340        0x0009 => {
341            match decode_software_version(tlv_value) {
342                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
343                Err(e) => format!("{{\"error\": \"{}\"}}", e),
344            }
345        }
346        0x000A => {
347            match decode_software_version_string(tlv_value) {
348                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
349                Err(e) => format!("{{\"error\": \"{}\"}}", e),
350            }
351        }
352        0x000B => {
353            match decode_manufacturing_date(tlv_value) {
354                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
355                Err(e) => format!("{{\"error\": \"{}\"}}", e),
356            }
357        }
358        0x000C => {
359            match decode_part_number(tlv_value) {
360                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
361                Err(e) => format!("{{\"error\": \"{}\"}}", e),
362            }
363        }
364        0x000D => {
365            match decode_product_url(tlv_value) {
366                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
367                Err(e) => format!("{{\"error\": \"{}\"}}", e),
368            }
369        }
370        0x000E => {
371            match decode_product_label(tlv_value) {
372                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
373                Err(e) => format!("{{\"error\": \"{}\"}}", e),
374            }
375        }
376        0x000F => {
377            match decode_serial_number(tlv_value) {
378                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
379                Err(e) => format!("{{\"error\": \"{}\"}}", e),
380            }
381        }
382        0x0010 => {
383            match decode_local_config_disabled(tlv_value) {
384                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
385                Err(e) => format!("{{\"error\": \"{}\"}}", e),
386            }
387        }
388        0x0011 => {
389            match decode_reachable(tlv_value) {
390                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
391                Err(e) => format!("{{\"error\": \"{}\"}}", e),
392            }
393        }
394        0x0012 => {
395            match decode_unique_id(tlv_value) {
396                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
397                Err(e) => format!("{{\"error\": \"{}\"}}", e),
398            }
399        }
400        0x0013 => {
401            match decode_capability_minima(tlv_value) {
402                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
403                Err(e) => format!("{{\"error\": \"{}\"}}", e),
404            }
405        }
406        0x0014 => {
407            match decode_product_appearance(tlv_value) {
408                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
409                Err(e) => format!("{{\"error\": \"{}\"}}", e),
410            }
411        }
412        0x0015 => {
413            match decode_specification_version(tlv_value) {
414                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
415                Err(e) => format!("{{\"error\": \"{}\"}}", e),
416            }
417        }
418        0x0016 => {
419            match decode_max_paths_per_invoke(tlv_value) {
420                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
421                Err(e) => format!("{{\"error\": \"{}\"}}", e),
422            }
423        }
424        0x0018 => {
425            match decode_configuration_version(tlv_value) {
426                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
427                Err(e) => format!("{{\"error\": \"{}\"}}", e),
428            }
429        }
430        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
431    }
432}
433
434/// Get list of all attributes supported by this cluster
435/// 
436/// # Returns
437/// Vector of tuples containing (attribute_id, attribute_name)
438pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
439    vec![
440        (0x0000, "DataModelRevision"),
441        (0x0001, "VendorName"),
442        (0x0002, "VendorID"),
443        (0x0003, "ProductName"),
444        (0x0004, "ProductID"),
445        (0x0005, "NodeLabel"),
446        (0x0006, "Location"),
447        (0x0007, "HardwareVersion"),
448        (0x0008, "HardwareVersionString"),
449        (0x0009, "SoftwareVersion"),
450        (0x000A, "SoftwareVersionString"),
451        (0x000B, "ManufacturingDate"),
452        (0x000C, "PartNumber"),
453        (0x000D, "ProductURL"),
454        (0x000E, "ProductLabel"),
455        (0x000F, "SerialNumber"),
456        (0x0010, "LocalConfigDisabled"),
457        (0x0011, "Reachable"),
458        (0x0012, "UniqueID"),
459        (0x0013, "CapabilityMinima"),
460        (0x0014, "ProductAppearance"),
461        (0x0015, "SpecificationVersion"),
462        (0x0016, "MaxPathsPerInvoke"),
463        (0x0018, "ConfigurationVersion"),
464    ]
465}
466