matc/clusters/codec/
electrical_energy_measurement.rs

1//! Generated Matter TLV encoders and decoders for Electrical Energy Measurement Cluster
2//! Cluster ID: 0x0091
3//! 
4//! This file is automatically generated from ElectricalEnergyMeasurement.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct CumulativeEnergyReset {
15    pub imported_reset_timestamp: Option<u64>,
16    pub exported_reset_timestamp: Option<u64>,
17    pub imported_reset_systime: Option<u8>,
18    pub exported_reset_systime: Option<u8>,
19}
20
21#[derive(Debug, serde::Serialize)]
22pub struct EnergyMeasurement {
23    pub energy: Option<u8>,
24    pub start_timestamp: Option<u64>,
25    pub end_timestamp: Option<u64>,
26    pub start_systime: Option<u8>,
27    pub end_systime: Option<u8>,
28}
29
30// Attribute decoders
31
32/// Decode Accuracy attribute (0x0000)
33pub fn decode_accuracy(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
34    if let tlv::TlvItemValue::Int(v) = inp {
35        Ok(*v as u8)
36    } else {
37        Err(anyhow::anyhow!("Expected Integer"))
38    }
39}
40
41/// Decode CumulativeEnergyImported attribute (0x0001)
42pub fn decode_cumulative_energy_imported(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<EnergyMeasurement>> {
43    if let tlv::TlvItemValue::List(_fields) = inp {
44        // Struct with fields
45        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
46        Ok(Some(EnergyMeasurement {
47                energy: item.get_int(&[0]).map(|v| v as u8),
48                start_timestamp: item.get_int(&[1]),
49                end_timestamp: item.get_int(&[2]),
50                start_systime: item.get_int(&[3]).map(|v| v as u8),
51                end_systime: item.get_int(&[4]).map(|v| v as u8),
52        }))
53    //} else if let tlv::TlvItemValue::Null = inp {
54    //    // Null value for nullable struct
55    //    Ok(None)
56    } else {
57    Ok(None)
58    //    Err(anyhow::anyhow!("Expected struct fields or null"))
59    }
60}
61
62/// Decode CumulativeEnergyExported attribute (0x0002)
63pub fn decode_cumulative_energy_exported(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<EnergyMeasurement>> {
64    if let tlv::TlvItemValue::List(_fields) = inp {
65        // Struct with fields
66        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
67        Ok(Some(EnergyMeasurement {
68                energy: item.get_int(&[0]).map(|v| v as u8),
69                start_timestamp: item.get_int(&[1]),
70                end_timestamp: item.get_int(&[2]),
71                start_systime: item.get_int(&[3]).map(|v| v as u8),
72                end_systime: item.get_int(&[4]).map(|v| v as u8),
73        }))
74    //} else if let tlv::TlvItemValue::Null = inp {
75    //    // Null value for nullable struct
76    //    Ok(None)
77    } else {
78    Ok(None)
79    //    Err(anyhow::anyhow!("Expected struct fields or null"))
80    }
81}
82
83/// Decode PeriodicEnergyImported attribute (0x0003)
84pub fn decode_periodic_energy_imported(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<EnergyMeasurement>> {
85    if let tlv::TlvItemValue::List(_fields) = inp {
86        // Struct with fields
87        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
88        Ok(Some(EnergyMeasurement {
89                energy: item.get_int(&[0]).map(|v| v as u8),
90                start_timestamp: item.get_int(&[1]),
91                end_timestamp: item.get_int(&[2]),
92                start_systime: item.get_int(&[3]).map(|v| v as u8),
93                end_systime: item.get_int(&[4]).map(|v| v as u8),
94        }))
95    //} else if let tlv::TlvItemValue::Null = inp {
96    //    // Null value for nullable struct
97    //    Ok(None)
98    } else {
99    Ok(None)
100    //    Err(anyhow::anyhow!("Expected struct fields or null"))
101    }
102}
103
104/// Decode PeriodicEnergyExported attribute (0x0004)
105pub fn decode_periodic_energy_exported(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<EnergyMeasurement>> {
106    if let tlv::TlvItemValue::List(_fields) = inp {
107        // Struct with fields
108        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
109        Ok(Some(EnergyMeasurement {
110                energy: item.get_int(&[0]).map(|v| v as u8),
111                start_timestamp: item.get_int(&[1]),
112                end_timestamp: item.get_int(&[2]),
113                start_systime: item.get_int(&[3]).map(|v| v as u8),
114                end_systime: item.get_int(&[4]).map(|v| v as u8),
115        }))
116    //} else if let tlv::TlvItemValue::Null = inp {
117    //    // Null value for nullable struct
118    //    Ok(None)
119    } else {
120    Ok(None)
121    //    Err(anyhow::anyhow!("Expected struct fields or null"))
122    }
123}
124
125/// Decode CumulativeEnergyReset attribute (0x0005)
126pub fn decode_cumulative_energy_reset(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<CumulativeEnergyReset>> {
127    if let tlv::TlvItemValue::List(_fields) = inp {
128        // Struct with fields
129        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
130        Ok(Some(CumulativeEnergyReset {
131                imported_reset_timestamp: item.get_int(&[0]),
132                exported_reset_timestamp: item.get_int(&[1]),
133                imported_reset_systime: item.get_int(&[2]).map(|v| v as u8),
134                exported_reset_systime: item.get_int(&[3]).map(|v| v as u8),
135        }))
136    //} else if let tlv::TlvItemValue::Null = inp {
137    //    // Null value for nullable struct
138    //    Ok(None)
139    } else {
140    Ok(None)
141    //    Err(anyhow::anyhow!("Expected struct fields or null"))
142    }
143}
144
145
146// JSON dispatcher function
147
148/// Decode attribute value and return as JSON string
149/// 
150/// # Parameters
151/// * `cluster_id` - The cluster identifier
152/// * `attribute_id` - The attribute identifier
153/// * `tlv_value` - The TLV value to decode
154/// 
155/// # Returns
156/// JSON string representation of the decoded value or error
157pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
158    // Verify this is the correct cluster
159    if cluster_id != 0x0091 {
160        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0091, got {}\"}}", cluster_id);
161    }
162    
163    match attribute_id {
164        0x0000 => {
165            match decode_accuracy(tlv_value) {
166                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
167                Err(e) => format!("{{\"error\": \"{}\"}}", e),
168            }
169        }
170        0x0001 => {
171            match decode_cumulative_energy_imported(tlv_value) {
172                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
173                Err(e) => format!("{{\"error\": \"{}\"}}", e),
174            }
175        }
176        0x0002 => {
177            match decode_cumulative_energy_exported(tlv_value) {
178                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
179                Err(e) => format!("{{\"error\": \"{}\"}}", e),
180            }
181        }
182        0x0003 => {
183            match decode_periodic_energy_imported(tlv_value) {
184                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
185                Err(e) => format!("{{\"error\": \"{}\"}}", e),
186            }
187        }
188        0x0004 => {
189            match decode_periodic_energy_exported(tlv_value) {
190                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
191                Err(e) => format!("{{\"error\": \"{}\"}}", e),
192            }
193        }
194        0x0005 => {
195            match decode_cumulative_energy_reset(tlv_value) {
196                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
197                Err(e) => format!("{{\"error\": \"{}\"}}", e),
198            }
199        }
200        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
201    }
202}
203
204/// Get list of all attributes supported by this cluster
205/// 
206/// # Returns
207/// Vector of tuples containing (attribute_id, attribute_name)
208pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
209    vec![
210        (0x0000, "Accuracy"),
211        (0x0001, "CumulativeEnergyImported"),
212        (0x0002, "CumulativeEnergyExported"),
213        (0x0003, "PeriodicEnergyImported"),
214        (0x0004, "PeriodicEnergyExported"),
215        (0x0005, "CumulativeEnergyReset"),
216    ]
217}
218