matc/clusters/codec/
meter_identification.rs

1//! Matter TLV encoders and decoders for Meter Identification Cluster
2//! Cluster ID: 0x0B06
3//!
4//! This file is automatically generated from MeterIdentification.xml
5
6#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13// Enum definitions
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
16#[repr(u8)]
17pub enum MeterType {
18    /// Utility Meter
19    Utility = 0,
20    /// Private Meter
21    Private = 1,
22    /// Generic Meter
23    Generic = 2,
24}
25
26impl MeterType {
27    /// Convert from u8 value
28    pub fn from_u8(value: u8) -> Option<Self> {
29        match value {
30            0 => Some(MeterType::Utility),
31            1 => Some(MeterType::Private),
32            2 => Some(MeterType::Generic),
33            _ => None,
34        }
35    }
36
37    /// Convert to u8 value
38    pub fn to_u8(self) -> u8 {
39        self as u8
40    }
41}
42
43impl From<MeterType> for u8 {
44    fn from(val: MeterType) -> Self {
45        val as u8
46    }
47}
48
49// Attribute decoders
50
51/// Decode MeterType attribute (0x0000)
52pub fn decode_meter_type(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<MeterType>> {
53    if let tlv::TlvItemValue::Int(v) = inp {
54        Ok(MeterType::from_u8(*v as u8))
55    } else {
56        Ok(None)
57    }
58}
59
60/// Decode PointOfDelivery attribute (0x0001)
61pub fn decode_point_of_delivery(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<String>> {
62    if let tlv::TlvItemValue::String(v) = inp {
63        Ok(Some(v.clone()))
64    } else {
65        Ok(None)
66    }
67}
68
69/// Decode MeterSerialNumber attribute (0x0002)
70pub fn decode_meter_serial_number(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<String>> {
71    if let tlv::TlvItemValue::String(v) = inp {
72        Ok(Some(v.clone()))
73    } else {
74        Ok(None)
75    }
76}
77
78/// Decode ProtocolVersion attribute (0x0003)
79pub fn decode_protocol_version(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<String>> {
80    if let tlv::TlvItemValue::String(v) = inp {
81        Ok(Some(v.clone()))
82    } else {
83        Ok(None)
84    }
85}
86
87/// Decode PowerThreshold attribute (0x0004)
88pub fn decode_power_threshold(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
89    if let tlv::TlvItemValue::Int(v) = inp {
90        Ok(Some(*v as u8))
91    } else {
92        Ok(None)
93    }
94}
95
96
97// JSON dispatcher function
98
99/// Decode attribute value and return as JSON string
100///
101/// # Parameters
102/// * `cluster_id` - The cluster identifier
103/// * `attribute_id` - The attribute identifier
104/// * `tlv_value` - The TLV value to decode
105///
106/// # Returns
107/// JSON string representation of the decoded value or error
108pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
109    // Verify this is the correct cluster
110    if cluster_id != 0x0B06 {
111        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0B06, got {}\"}}", cluster_id);
112    }
113
114    match attribute_id {
115        0x0000 => {
116            match decode_meter_type(tlv_value) {
117                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
118                Err(e) => format!("{{\"error\": \"{}\"}}", e),
119            }
120        }
121        0x0001 => {
122            match decode_point_of_delivery(tlv_value) {
123                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
124                Err(e) => format!("{{\"error\": \"{}\"}}", e),
125            }
126        }
127        0x0002 => {
128            match decode_meter_serial_number(tlv_value) {
129                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
130                Err(e) => format!("{{\"error\": \"{}\"}}", e),
131            }
132        }
133        0x0003 => {
134            match decode_protocol_version(tlv_value) {
135                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
136                Err(e) => format!("{{\"error\": \"{}\"}}", e),
137            }
138        }
139        0x0004 => {
140            match decode_power_threshold(tlv_value) {
141                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
142                Err(e) => format!("{{\"error\": \"{}\"}}", e),
143            }
144        }
145        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
146    }
147}
148
149/// Get list of all attributes supported by this cluster
150///
151/// # Returns
152/// Vector of tuples containing (attribute_id, attribute_name)
153pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
154    vec![
155        (0x0000, "MeterType"),
156        (0x0001, "PointOfDelivery"),
157        (0x0002, "MeterSerialNumber"),
158        (0x0003, "ProtocolVersion"),
159        (0x0004, "PowerThreshold"),
160    ]
161}
162
163// Typed facade (invokes + reads)
164
165/// Read `MeterType` attribute from cluster `Meter Identification`.
166pub async fn read_meter_type(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<MeterType>> {
167    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_METERTYPE).await?;
168    decode_meter_type(&tlv)
169}
170
171/// Read `PointOfDelivery` attribute from cluster `Meter Identification`.
172pub async fn read_point_of_delivery(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<String>> {
173    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_POINTOFDELIVERY).await?;
174    decode_point_of_delivery(&tlv)
175}
176
177/// Read `MeterSerialNumber` attribute from cluster `Meter Identification`.
178pub async fn read_meter_serial_number(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<String>> {
179    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_METERSERIALNUMBER).await?;
180    decode_meter_serial_number(&tlv)
181}
182
183/// Read `ProtocolVersion` attribute from cluster `Meter Identification`.
184pub async fn read_protocol_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<String>> {
185    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_PROTOCOLVERSION).await?;
186    decode_protocol_version(&tlv)
187}
188
189/// Read `PowerThreshold` attribute from cluster `Meter Identification`.
190pub async fn read_power_threshold(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
191    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_POWERTHRESHOLD).await?;
192    decode_power_threshold(&tlv)
193}
194