matc/clusters/codec/
mode_rvc_run.rs

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