matc/clusters/codec/
mode_rvc_clean.rs

1//! Matter TLV encoders and decoders for RVC Clean Mode Cluster
2//! Cluster ID: 0x0055
3//!
4//! This file is automatically generated from Mode_RVCClean.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(u16)]
17pub enum ModeTag {
18    Auto = 0,
19    Quick = 1,
20    Quiet = 2,
21    Lownoise = 3,
22    Lowenergy = 4,
23    Vacation = 5,
24    Min = 6,
25    Max = 7,
26    Night = 8,
27    Day = 9,
28    Deepclean = 16384,
29    Vacuum = 16385,
30    Mop = 16386,
31    VacuumThenMop = 16387,
32}
33
34impl ModeTag {
35    /// Convert from u8 value (promoted to u16)
36    pub fn from_u8(value: u8) -> Option<Self> {
37        Self::from_u16(value as u16)
38    }
39
40    /// Convert from u16 value
41    pub fn from_u16(value: u16) -> Option<Self> {
42        match value {
43            0 => Some(ModeTag::Auto),
44            1 => Some(ModeTag::Quick),
45            2 => Some(ModeTag::Quiet),
46            3 => Some(ModeTag::Lownoise),
47            4 => Some(ModeTag::Lowenergy),
48            5 => Some(ModeTag::Vacation),
49            6 => Some(ModeTag::Min),
50            7 => Some(ModeTag::Max),
51            8 => Some(ModeTag::Night),
52            9 => Some(ModeTag::Day),
53            16384 => Some(ModeTag::Deepclean),
54            16385 => Some(ModeTag::Vacuum),
55            16386 => Some(ModeTag::Mop),
56            16387 => Some(ModeTag::VacuumThenMop),
57            _ => None,
58        }
59    }
60
61    /// Convert to u8 value (truncated if value > 255)
62    pub fn to_u8(self) -> u8 {
63        self as u8
64    }
65
66    /// Convert to u16 value
67    pub fn to_u16(self) -> u16 {
68        self as u16
69    }
70}
71
72impl From<ModeTag> for u16 {
73    fn from(val: ModeTag) -> Self {
74        val as u16
75    }
76}
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
79#[repr(u8)]
80pub enum StatusCode {
81    Cleaninginprogress = 64,
82}
83
84impl StatusCode {
85    /// Convert from u8 value
86    pub fn from_u8(value: u8) -> Option<Self> {
87        match value {
88            64 => Some(StatusCode::Cleaninginprogress),
89            _ => None,
90        }
91    }
92
93    /// Convert to u8 value
94    pub fn to_u8(self) -> u8 {
95        self as u8
96    }
97}
98
99impl From<StatusCode> for u8 {
100    fn from(val: StatusCode) -> Self {
101        val as u8
102    }
103}
104
105// Struct definitions
106
107#[derive(Debug, serde::Serialize)]
108pub struct ModeOption {
109    pub label: Option<u8>,
110    pub mode: Option<u8>,
111    pub mode_tags: Option<u8>,
112}
113
114// Attribute decoders
115
116/// Decode SupportedModes attribute (0x0000)
117pub fn decode_supported_modes(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
118    if let tlv::TlvItemValue::Int(v) = inp {
119        Ok(*v as u8)
120    } else {
121        Err(anyhow::anyhow!("Expected UInt8"))
122    }
123}
124
125/// Decode CurrentMode attribute (0x0001)
126pub fn decode_current_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
127    if let tlv::TlvItemValue::Int(v) = inp {
128        Ok(*v as u8)
129    } else {
130        Err(anyhow::anyhow!("Expected UInt8"))
131    }
132}
133
134/// Decode StartUpMode attribute (0x0002)
135pub fn decode_start_up_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
136    if let tlv::TlvItemValue::Int(v) = inp {
137        Ok(*v as u8)
138    } else {
139        Err(anyhow::anyhow!("Expected UInt8"))
140    }
141}
142
143/// Decode OnMode attribute (0x0003)
144pub fn decode_on_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
145    if let tlv::TlvItemValue::Int(v) = inp {
146        Ok(*v as u8)
147    } else {
148        Err(anyhow::anyhow!("Expected UInt8"))
149    }
150}
151
152
153// JSON dispatcher function
154
155/// Decode attribute value and return as JSON string
156///
157/// # Parameters
158/// * `cluster_id` - The cluster identifier
159/// * `attribute_id` - The attribute identifier
160/// * `tlv_value` - The TLV value to decode
161///
162/// # Returns
163/// JSON string representation of the decoded value or error
164pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
165    // Verify this is the correct cluster
166    if cluster_id != 0x0055 {
167        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0055, got {}\"}}", cluster_id);
168    }
169
170    match attribute_id {
171        0x0000 => {
172            match decode_supported_modes(tlv_value) {
173                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
174                Err(e) => format!("{{\"error\": \"{}\"}}", e),
175            }
176        }
177        0x0001 => {
178            match decode_current_mode(tlv_value) {
179                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
180                Err(e) => format!("{{\"error\": \"{}\"}}", e),
181            }
182        }
183        0x0002 => {
184            match decode_start_up_mode(tlv_value) {
185                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
186                Err(e) => format!("{{\"error\": \"{}\"}}", e),
187            }
188        }
189        0x0003 => {
190            match decode_on_mode(tlv_value) {
191                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
192                Err(e) => format!("{{\"error\": \"{}\"}}", e),
193            }
194        }
195        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
196    }
197}
198
199/// Get list of all attributes supported by this cluster
200///
201/// # Returns
202/// Vector of tuples containing (attribute_id, attribute_name)
203pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
204    vec![
205        (0x0000, "SupportedModes"),
206        (0x0001, "CurrentMode"),
207        (0x0002, "StartUpMode"),
208        (0x0003, "OnMode"),
209    ]
210}
211
212// Typed facade (invokes + reads)
213
214/// Read `SupportedModes` attribute from cluster `RVC Clean Mode`.
215pub async fn read_supported_modes(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
216    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_RVC_CLEAN_MODE, crate::clusters::defs::CLUSTER_RVC_CLEAN_MODE_ATTR_ID_SUPPORTEDMODES).await?;
217    decode_supported_modes(&tlv)
218}
219
220/// Read `CurrentMode` attribute from cluster `RVC Clean Mode`.
221pub async fn read_current_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
222    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_RVC_CLEAN_MODE, crate::clusters::defs::CLUSTER_RVC_CLEAN_MODE_ATTR_ID_CURRENTMODE).await?;
223    decode_current_mode(&tlv)
224}
225
226/// Read `StartUpMode` attribute from cluster `RVC Clean Mode`.
227pub async fn read_start_up_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
228    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_RVC_CLEAN_MODE, crate::clusters::defs::CLUSTER_RVC_CLEAN_MODE_ATTR_ID_STARTUPMODE).await?;
229    decode_start_up_mode(&tlv)
230}
231
232/// Read `OnMode` attribute from cluster `RVC Clean Mode`.
233pub async fn read_on_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
234    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_RVC_CLEAN_MODE, crate::clusters::defs::CLUSTER_RVC_CLEAN_MODE_ATTR_ID_ONMODE).await?;
235    decode_on_mode(&tlv)
236}
237