matc/clusters/codec/
energy_preference.rs

1//! Matter TLV encoders and decoders for Energy Preference Cluster
2//! Cluster ID: 0x009B
3//!
4//! This file is automatically generated from EnergyPreference.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 EnergyPriority {
18    /// User comfort
19    Comfort = 0,
20    /// Speed of operation
21    Speed = 1,
22    /// Amount of Energy consumed by the device
23    Efficiency = 2,
24    /// Amount of water consumed by the device
25    Waterconsumption = 3,
26}
27
28impl EnergyPriority {
29    /// Convert from u8 value
30    pub fn from_u8(value: u8) -> Option<Self> {
31        match value {
32            0 => Some(EnergyPriority::Comfort),
33            1 => Some(EnergyPriority::Speed),
34            2 => Some(EnergyPriority::Efficiency),
35            3 => Some(EnergyPriority::Waterconsumption),
36            _ => None,
37        }
38    }
39
40    /// Convert to u8 value
41    pub fn to_u8(self) -> u8 {
42        self as u8
43    }
44}
45
46impl From<EnergyPriority> for u8 {
47    fn from(val: EnergyPriority) -> Self {
48        val as u8
49    }
50}
51
52// Struct definitions
53
54#[derive(Debug, serde::Serialize)]
55pub struct Balance {
56    pub step: Option<u8>,
57    pub label: Option<String>,
58}
59
60// Attribute decoders
61
62/// Decode EnergyBalances attribute (0x0000)
63pub fn decode_energy_balances(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Balance>> {
64    let mut res = Vec::new();
65    if let tlv::TlvItemValue::List(v) = inp {
66        for item in v {
67            res.push(Balance {
68                step: item.get_int(&[0]).map(|v| v as u8),
69                label: item.get_string_owned(&[1]),
70            });
71        }
72    }
73    Ok(res)
74}
75
76/// Decode CurrentEnergyBalance attribute (0x0001)
77pub fn decode_current_energy_balance(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
78    if let tlv::TlvItemValue::Int(v) = inp {
79        Ok(*v as u8)
80    } else {
81        Err(anyhow::anyhow!("Expected UInt8"))
82    }
83}
84
85/// Decode EnergyPriorities attribute (0x0002)
86pub fn decode_energy_priorities(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<EnergyPriority>> {
87    let mut res = Vec::new();
88    if let tlv::TlvItemValue::List(v) = inp {
89        for item in v {
90            if let tlv::TlvItemValue::Int(i) = &item.value {
91                if let Some(enum_val) = EnergyPriority::from_u8(*i as u8) {
92                    res.push(enum_val);
93                }
94            }
95        }
96    }
97    Ok(res)
98}
99
100/// Decode LowPowerModeSensitivities attribute (0x0003)
101pub fn decode_low_power_mode_sensitivities(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Balance>> {
102    let mut res = Vec::new();
103    if let tlv::TlvItemValue::List(v) = inp {
104        for item in v {
105            res.push(Balance {
106                step: item.get_int(&[0]).map(|v| v as u8),
107                label: item.get_string_owned(&[1]),
108            });
109        }
110    }
111    Ok(res)
112}
113
114/// Decode CurrentLowPowerModeSensitivity attribute (0x0004)
115pub fn decode_current_low_power_mode_sensitivity(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
116    if let tlv::TlvItemValue::Int(v) = inp {
117        Ok(*v as u8)
118    } else {
119        Err(anyhow::anyhow!("Expected UInt8"))
120    }
121}
122
123
124// JSON dispatcher function
125
126/// Decode attribute value and return as JSON string
127///
128/// # Parameters
129/// * `cluster_id` - The cluster identifier
130/// * `attribute_id` - The attribute identifier
131/// * `tlv_value` - The TLV value to decode
132///
133/// # Returns
134/// JSON string representation of the decoded value or error
135pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
136    // Verify this is the correct cluster
137    if cluster_id != 0x009B {
138        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x009B, got {}\"}}", cluster_id);
139    }
140
141    match attribute_id {
142        0x0000 => {
143            match decode_energy_balances(tlv_value) {
144                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
145                Err(e) => format!("{{\"error\": \"{}\"}}", e),
146            }
147        }
148        0x0001 => {
149            match decode_current_energy_balance(tlv_value) {
150                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
151                Err(e) => format!("{{\"error\": \"{}\"}}", e),
152            }
153        }
154        0x0002 => {
155            match decode_energy_priorities(tlv_value) {
156                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
157                Err(e) => format!("{{\"error\": \"{}\"}}", e),
158            }
159        }
160        0x0003 => {
161            match decode_low_power_mode_sensitivities(tlv_value) {
162                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
163                Err(e) => format!("{{\"error\": \"{}\"}}", e),
164            }
165        }
166        0x0004 => {
167            match decode_current_low_power_mode_sensitivity(tlv_value) {
168                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
169                Err(e) => format!("{{\"error\": \"{}\"}}", e),
170            }
171        }
172        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
173    }
174}
175
176/// Get list of all attributes supported by this cluster
177///
178/// # Returns
179/// Vector of tuples containing (attribute_id, attribute_name)
180pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
181    vec![
182        (0x0000, "EnergyBalances"),
183        (0x0001, "CurrentEnergyBalance"),
184        (0x0002, "EnergyPriorities"),
185        (0x0003, "LowPowerModeSensitivities"),
186        (0x0004, "CurrentLowPowerModeSensitivity"),
187    ]
188}
189
190// Typed facade (invokes + reads)
191
192/// Read `EnergyBalances` attribute from cluster `Energy Preference`.
193pub async fn read_energy_balances(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<Balance>> {
194    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ENERGY_PREFERENCE, crate::clusters::defs::CLUSTER_ENERGY_PREFERENCE_ATTR_ID_ENERGYBALANCES).await?;
195    decode_energy_balances(&tlv)
196}
197
198/// Read `CurrentEnergyBalance` attribute from cluster `Energy Preference`.
199pub async fn read_current_energy_balance(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
200    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ENERGY_PREFERENCE, crate::clusters::defs::CLUSTER_ENERGY_PREFERENCE_ATTR_ID_CURRENTENERGYBALANCE).await?;
201    decode_current_energy_balance(&tlv)
202}
203
204/// Read `EnergyPriorities` attribute from cluster `Energy Preference`.
205pub async fn read_energy_priorities(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<EnergyPriority>> {
206    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ENERGY_PREFERENCE, crate::clusters::defs::CLUSTER_ENERGY_PREFERENCE_ATTR_ID_ENERGYPRIORITIES).await?;
207    decode_energy_priorities(&tlv)
208}
209
210/// Read `LowPowerModeSensitivities` attribute from cluster `Energy Preference`.
211pub async fn read_low_power_mode_sensitivities(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<Balance>> {
212    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ENERGY_PREFERENCE, crate::clusters::defs::CLUSTER_ENERGY_PREFERENCE_ATTR_ID_LOWPOWERMODESENSITIVITIES).await?;
213    decode_low_power_mode_sensitivities(&tlv)
214}
215
216/// Read `CurrentLowPowerModeSensitivity` attribute from cluster `Energy Preference`.
217pub async fn read_current_low_power_mode_sensitivity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
218    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ENERGY_PREFERENCE, crate::clusters::defs::CLUSTER_ENERGY_PREFERENCE_ATTR_ID_CURRENTLOWPOWERMODESENSITIVITY).await?;
219    decode_current_low_power_mode_sensitivity(&tlv)
220}
221