matc/clusters/codec/
electrical_power_measurement.rs

1//! Generated Matter TLV encoders and decoders for Electrical Power Measurement Cluster
2//! Cluster ID: 0x0090
3//! 
4//! This file is automatically generated from ElectricalPowerMeasurement.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct HarmonicMeasurement {
15    pub order: Option<u8>,
16    pub measurement: Option<i64>,
17}
18
19#[derive(Debug, serde::Serialize)]
20pub struct MeasurementRange {
21    pub measurement_type: Option<u8>,
22    pub min: Option<i64>,
23    pub max: Option<i64>,
24    pub start_timestamp: Option<u64>,
25    pub end_timestamp: Option<u64>,
26    pub min_timestamp: Option<u64>,
27    pub max_timestamp: Option<u64>,
28    pub start_systime: Option<u8>,
29    pub end_systime: Option<u8>,
30    pub min_systime: Option<u8>,
31    pub max_systime: Option<u8>,
32}
33
34// Attribute decoders
35
36/// Decode PowerMode attribute (0x0000)
37pub fn decode_power_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
38    if let tlv::TlvItemValue::Int(v) = inp {
39        Ok(*v as u8)
40    } else {
41        Err(anyhow::anyhow!("Expected Integer"))
42    }
43}
44
45/// Decode NumberOfMeasurementTypes attribute (0x0001)
46pub fn decode_number_of_measurement_types(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
47    if let tlv::TlvItemValue::Int(v) = inp {
48        Ok(*v as u8)
49    } else {
50        Err(anyhow::anyhow!("Expected Integer"))
51    }
52}
53
54/// Decode Accuracy attribute (0x0002)
55pub fn decode_accuracy(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<String>> {
56    let mut res = Vec::new();
57    if let tlv::TlvItemValue::List(v) = inp {
58        for item in v {
59            if let tlv::TlvItemValue::String(s) = &item.value {
60                res.push(s.clone());
61            }
62        }
63    }
64    Ok(res)
65}
66
67/// Decode Ranges attribute (0x0003)
68pub fn decode_ranges(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<MeasurementRange>> {
69    let mut res = Vec::new();
70    if let tlv::TlvItemValue::List(v) = inp {
71        for item in v {
72            res.push(MeasurementRange {
73                measurement_type: item.get_int(&[0]).map(|v| v as u8),
74                min: item.get_int(&[1]).map(|v| v as i64),
75                max: item.get_int(&[2]).map(|v| v as i64),
76                start_timestamp: item.get_int(&[3]),
77                end_timestamp: item.get_int(&[4]),
78                min_timestamp: item.get_int(&[5]),
79                max_timestamp: item.get_int(&[6]),
80                start_systime: item.get_int(&[7]).map(|v| v as u8),
81                end_systime: item.get_int(&[8]).map(|v| v as u8),
82                min_systime: item.get_int(&[9]).map(|v| v as u8),
83                max_systime: item.get_int(&[10]).map(|v| v as u8),
84            });
85        }
86    }
87    Ok(res)
88}
89
90/// Decode Voltage attribute (0x0004)
91pub fn decode_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
92    if let tlv::TlvItemValue::Int(v) = inp {
93        Ok(Some(*v as u8))
94    } else {
95        Ok(None)
96    }
97}
98
99/// Decode ActiveCurrent attribute (0x0005)
100pub fn decode_active_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
101    if let tlv::TlvItemValue::Int(v) = inp {
102        Ok(Some(*v as u8))
103    } else {
104        Ok(None)
105    }
106}
107
108/// Decode ReactiveCurrent attribute (0x0006)
109pub fn decode_reactive_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
110    if let tlv::TlvItemValue::Int(v) = inp {
111        Ok(Some(*v as u8))
112    } else {
113        Ok(None)
114    }
115}
116
117/// Decode ApparentCurrent attribute (0x0007)
118pub fn decode_apparent_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
119    if let tlv::TlvItemValue::Int(v) = inp {
120        Ok(Some(*v as u8))
121    } else {
122        Ok(None)
123    }
124}
125
126/// Decode ActivePower attribute (0x0008)
127pub fn decode_active_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
128    if let tlv::TlvItemValue::Int(v) = inp {
129        Ok(Some(*v as u8))
130    } else {
131        Ok(None)
132    }
133}
134
135/// Decode ReactivePower attribute (0x0009)
136pub fn decode_reactive_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
137    if let tlv::TlvItemValue::Int(v) = inp {
138        Ok(Some(*v as u8))
139    } else {
140        Ok(None)
141    }
142}
143
144/// Decode ApparentPower attribute (0x000A)
145pub fn decode_apparent_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
146    if let tlv::TlvItemValue::Int(v) = inp {
147        Ok(Some(*v as u8))
148    } else {
149        Ok(None)
150    }
151}
152
153/// Decode RMSVoltage attribute (0x000B)
154pub fn decode_rms_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
155    if let tlv::TlvItemValue::Int(v) = inp {
156        Ok(Some(*v as u8))
157    } else {
158        Ok(None)
159    }
160}
161
162/// Decode RMSCurrent attribute (0x000C)
163pub fn decode_rms_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
164    if let tlv::TlvItemValue::Int(v) = inp {
165        Ok(Some(*v as u8))
166    } else {
167        Ok(None)
168    }
169}
170
171/// Decode RMSPower attribute (0x000D)
172pub fn decode_rms_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
173    if let tlv::TlvItemValue::Int(v) = inp {
174        Ok(Some(*v as u8))
175    } else {
176        Ok(None)
177    }
178}
179
180/// Decode Frequency attribute (0x000E)
181pub fn decode_frequency(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<i64>> {
182    if let tlv::TlvItemValue::Int(v) = inp {
183        Ok(Some(*v as i64))
184    } else {
185        Ok(None)
186    }
187}
188
189/// Decode HarmonicCurrents attribute (0x000F)
190pub fn decode_harmonic_currents(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<HarmonicMeasurement>> {
191    let mut res = Vec::new();
192    if let tlv::TlvItemValue::List(v) = inp {
193        for item in v {
194            res.push(HarmonicMeasurement {
195                order: item.get_int(&[0]).map(|v| v as u8),
196                measurement: item.get_int(&[1]).map(|v| v as i64),
197            });
198        }
199    }
200    Ok(res)
201}
202
203/// Decode HarmonicPhases attribute (0x0010)
204pub fn decode_harmonic_phases(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<HarmonicMeasurement>> {
205    let mut res = Vec::new();
206    if let tlv::TlvItemValue::List(v) = inp {
207        for item in v {
208            res.push(HarmonicMeasurement {
209                order: item.get_int(&[0]).map(|v| v as u8),
210                measurement: item.get_int(&[1]).map(|v| v as i64),
211            });
212        }
213    }
214    Ok(res)
215}
216
217/// Decode PowerFactor attribute (0x0011)
218pub fn decode_power_factor(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<i64>> {
219    if let tlv::TlvItemValue::Int(v) = inp {
220        Ok(Some(*v as i64))
221    } else {
222        Ok(None)
223    }
224}
225
226/// Decode NeutralCurrent attribute (0x0012)
227pub fn decode_neutral_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
228    if let tlv::TlvItemValue::Int(v) = inp {
229        Ok(Some(*v as u8))
230    } else {
231        Ok(None)
232    }
233}
234
235
236// JSON dispatcher function
237
238/// Decode attribute value and return as JSON string
239/// 
240/// # Parameters
241/// * `cluster_id` - The cluster identifier
242/// * `attribute_id` - The attribute identifier
243/// * `tlv_value` - The TLV value to decode
244/// 
245/// # Returns
246/// JSON string representation of the decoded value or error
247pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
248    // Verify this is the correct cluster
249    if cluster_id != 0x0090 {
250        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0090, got {}\"}}", cluster_id);
251    }
252    
253    match attribute_id {
254        0x0000 => {
255            match decode_power_mode(tlv_value) {
256                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
257                Err(e) => format!("{{\"error\": \"{}\"}}", e),
258            }
259        }
260        0x0001 => {
261            match decode_number_of_measurement_types(tlv_value) {
262                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
263                Err(e) => format!("{{\"error\": \"{}\"}}", e),
264            }
265        }
266        0x0002 => {
267            match decode_accuracy(tlv_value) {
268                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
269                Err(e) => format!("{{\"error\": \"{}\"}}", e),
270            }
271        }
272        0x0003 => {
273            match decode_ranges(tlv_value) {
274                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
275                Err(e) => format!("{{\"error\": \"{}\"}}", e),
276            }
277        }
278        0x0004 => {
279            match decode_voltage(tlv_value) {
280                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
281                Err(e) => format!("{{\"error\": \"{}\"}}", e),
282            }
283        }
284        0x0005 => {
285            match decode_active_current(tlv_value) {
286                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
287                Err(e) => format!("{{\"error\": \"{}\"}}", e),
288            }
289        }
290        0x0006 => {
291            match decode_reactive_current(tlv_value) {
292                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
293                Err(e) => format!("{{\"error\": \"{}\"}}", e),
294            }
295        }
296        0x0007 => {
297            match decode_apparent_current(tlv_value) {
298                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
299                Err(e) => format!("{{\"error\": \"{}\"}}", e),
300            }
301        }
302        0x0008 => {
303            match decode_active_power(tlv_value) {
304                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
305                Err(e) => format!("{{\"error\": \"{}\"}}", e),
306            }
307        }
308        0x0009 => {
309            match decode_reactive_power(tlv_value) {
310                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
311                Err(e) => format!("{{\"error\": \"{}\"}}", e),
312            }
313        }
314        0x000A => {
315            match decode_apparent_power(tlv_value) {
316                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
317                Err(e) => format!("{{\"error\": \"{}\"}}", e),
318            }
319        }
320        0x000B => {
321            match decode_rms_voltage(tlv_value) {
322                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
323                Err(e) => format!("{{\"error\": \"{}\"}}", e),
324            }
325        }
326        0x000C => {
327            match decode_rms_current(tlv_value) {
328                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
329                Err(e) => format!("{{\"error\": \"{}\"}}", e),
330            }
331        }
332        0x000D => {
333            match decode_rms_power(tlv_value) {
334                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
335                Err(e) => format!("{{\"error\": \"{}\"}}", e),
336            }
337        }
338        0x000E => {
339            match decode_frequency(tlv_value) {
340                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
341                Err(e) => format!("{{\"error\": \"{}\"}}", e),
342            }
343        }
344        0x000F => {
345            match decode_harmonic_currents(tlv_value) {
346                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
347                Err(e) => format!("{{\"error\": \"{}\"}}", e),
348            }
349        }
350        0x0010 => {
351            match decode_harmonic_phases(tlv_value) {
352                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
353                Err(e) => format!("{{\"error\": \"{}\"}}", e),
354            }
355        }
356        0x0011 => {
357            match decode_power_factor(tlv_value) {
358                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
359                Err(e) => format!("{{\"error\": \"{}\"}}", e),
360            }
361        }
362        0x0012 => {
363            match decode_neutral_current(tlv_value) {
364                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
365                Err(e) => format!("{{\"error\": \"{}\"}}", e),
366            }
367        }
368        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
369    }
370}
371
372/// Get list of all attributes supported by this cluster
373/// 
374/// # Returns
375/// Vector of tuples containing (attribute_id, attribute_name)
376pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
377    vec![
378        (0x0000, "PowerMode"),
379        (0x0001, "NumberOfMeasurementTypes"),
380        (0x0002, "Accuracy"),
381        (0x0003, "Ranges"),
382        (0x0004, "Voltage"),
383        (0x0005, "ActiveCurrent"),
384        (0x0006, "ReactiveCurrent"),
385        (0x0007, "ApparentCurrent"),
386        (0x0008, "ActivePower"),
387        (0x0009, "ReactivePower"),
388        (0x000A, "ApparentPower"),
389        (0x000B, "RMSVoltage"),
390        (0x000C, "RMSCurrent"),
391        (0x000D, "RMSPower"),
392        (0x000E, "Frequency"),
393        (0x000F, "HarmonicCurrents"),
394        (0x0010, "HarmonicPhases"),
395        (0x0011, "PowerFactor"),
396        (0x0012, "NeutralCurrent"),
397    ]
398}
399