matc/clusters/codec/
diagnostics_software.rs

1//! Matter TLV encoders and decoders for Software Diagnostics Cluster
2//! Cluster ID: 0x0034
3//!
4//! This file is automatically generated from DiagnosticsSoftware.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// Struct definitions
15
16#[derive(Debug, serde::Serialize)]
17pub struct ThreadMetrics {
18    pub id: Option<u64>,
19    pub name: Option<String>,
20    pub stack_free_current: Option<u32>,
21    pub stack_free_minimum: Option<u32>,
22    pub stack_size: Option<u32>,
23}
24
25// Command encoders
26
27// Attribute decoders
28
29/// Decode ThreadMetrics attribute (0x0000)
30pub fn decode_thread_metrics(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<ThreadMetrics>> {
31    let mut res = Vec::new();
32    if let tlv::TlvItemValue::List(v) = inp {
33        for item in v {
34            res.push(ThreadMetrics {
35                id: item.get_int(&[0]),
36                name: item.get_string_owned(&[1]),
37                stack_free_current: item.get_int(&[2]).map(|v| v as u32),
38                stack_free_minimum: item.get_int(&[3]).map(|v| v as u32),
39                stack_size: item.get_int(&[4]).map(|v| v as u32),
40            });
41        }
42    }
43    Ok(res)
44}
45
46/// Decode CurrentHeapFree attribute (0x0001)
47pub fn decode_current_heap_free(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
48    if let tlv::TlvItemValue::Int(v) = inp {
49        Ok(*v)
50    } else {
51        Err(anyhow::anyhow!("Expected UInt64"))
52    }
53}
54
55/// Decode CurrentHeapUsed attribute (0x0002)
56pub fn decode_current_heap_used(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
57    if let tlv::TlvItemValue::Int(v) = inp {
58        Ok(*v)
59    } else {
60        Err(anyhow::anyhow!("Expected UInt64"))
61    }
62}
63
64/// Decode CurrentHeapHighWatermark attribute (0x0003)
65pub fn decode_current_heap_high_watermark(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
66    if let tlv::TlvItemValue::Int(v) = inp {
67        Ok(*v)
68    } else {
69        Err(anyhow::anyhow!("Expected UInt64"))
70    }
71}
72
73
74// JSON dispatcher function
75
76/// Decode attribute value and return as JSON string
77///
78/// # Parameters
79/// * `cluster_id` - The cluster identifier
80/// * `attribute_id` - The attribute identifier
81/// * `tlv_value` - The TLV value to decode
82///
83/// # Returns
84/// JSON string representation of the decoded value or error
85pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
86    // Verify this is the correct cluster
87    if cluster_id != 0x0034 {
88        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0034, got {}\"}}", cluster_id);
89    }
90
91    match attribute_id {
92        0x0000 => {
93            match decode_thread_metrics(tlv_value) {
94                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
95                Err(e) => format!("{{\"error\": \"{}\"}}", e),
96            }
97        }
98        0x0001 => {
99            match decode_current_heap_free(tlv_value) {
100                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
101                Err(e) => format!("{{\"error\": \"{}\"}}", e),
102            }
103        }
104        0x0002 => {
105            match decode_current_heap_used(tlv_value) {
106                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
107                Err(e) => format!("{{\"error\": \"{}\"}}", e),
108            }
109        }
110        0x0003 => {
111            match decode_current_heap_high_watermark(tlv_value) {
112                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
113                Err(e) => format!("{{\"error\": \"{}\"}}", e),
114            }
115        }
116        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
117    }
118}
119
120/// Get list of all attributes supported by this cluster
121///
122/// # Returns
123/// Vector of tuples containing (attribute_id, attribute_name)
124pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
125    vec![
126        (0x0000, "ThreadMetrics"),
127        (0x0001, "CurrentHeapFree"),
128        (0x0002, "CurrentHeapUsed"),
129        (0x0003, "CurrentHeapHighWatermark"),
130    ]
131}
132
133#[derive(Debug, serde::Serialize)]
134pub struct SoftwareFaultEvent {
135    pub id: Option<u64>,
136    pub name: Option<String>,
137    #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
138    pub fault_recording: Option<Vec<u8>>,
139}
140
141// Event decoders
142
143/// Decode SoftwareFault event (0x00, priority: info)
144pub fn decode_software_fault_event(inp: &tlv::TlvItemValue) -> anyhow::Result<SoftwareFaultEvent> {
145    if let tlv::TlvItemValue::List(_fields) = inp {
146        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
147        Ok(SoftwareFaultEvent {
148                                id: item.get_int(&[0]),
149                                name: item.get_string_owned(&[1]),
150                                fault_recording: item.get_octet_string_owned(&[2]),
151        })
152    } else {
153        Err(anyhow::anyhow!("Expected struct fields"))
154    }
155}
156