matc/clusters/codec/
actions_cluster.rs

1//! Generated Matter TLV encoders and decoders for Actions Cluster
2//! Cluster ID: 0x0025
3//! 
4//! This file is automatically generated from ActionsCluster.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct Action {
15    pub action_id: Option<u16>,
16    pub name: Option<String>,
17    pub type_: Option<u8>,
18    pub endpoint_list_id: Option<u16>,
19    pub supported_commands: Option<u8>,
20    pub state: Option<u8>,
21}
22
23#[derive(Debug, serde::Serialize)]
24pub struct EndpointList {
25    pub endpoint_list_id: Option<u16>,
26    pub name: Option<String>,
27    pub type_: Option<u8>,
28    pub endpoints: Option<Vec<u16>>,
29}
30
31// Command encoders
32
33/// Encode InstantAction command (0x00)
34pub fn encode_instant_action(action_id: u16, invoke_id: u32) -> anyhow::Result<Vec<u8>> {
35    let tlv = tlv::TlvItemEnc {
36        tag: 0,
37        value: tlv::TlvItemValueEnc::StructInvisible(vec![
38        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
39        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
40        ]),
41    };
42    Ok(tlv.encode()?)
43}
44
45/// Encode InstantActionWithTransition command (0x01)
46pub fn encode_instant_action_with_transition(action_id: u16, invoke_id: u32, transition_time: u16) -> anyhow::Result<Vec<u8>> {
47    let tlv = tlv::TlvItemEnc {
48        tag: 0,
49        value: tlv::TlvItemValueEnc::StructInvisible(vec![
50        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
51        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
52        (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
53        ]),
54    };
55    Ok(tlv.encode()?)
56}
57
58/// Encode StartAction command (0x02)
59pub fn encode_start_action(action_id: u16, invoke_id: u32) -> anyhow::Result<Vec<u8>> {
60    let tlv = tlv::TlvItemEnc {
61        tag: 0,
62        value: tlv::TlvItemValueEnc::StructInvisible(vec![
63        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
64        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
65        ]),
66    };
67    Ok(tlv.encode()?)
68}
69
70/// Encode StartActionWithDuration command (0x03)
71pub fn encode_start_action_with_duration(action_id: u16, invoke_id: u32, duration: u32) -> anyhow::Result<Vec<u8>> {
72    let tlv = tlv::TlvItemEnc {
73        tag: 0,
74        value: tlv::TlvItemValueEnc::StructInvisible(vec![
75        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
76        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
77        (2, tlv::TlvItemValueEnc::UInt32(duration)).into(),
78        ]),
79    };
80    Ok(tlv.encode()?)
81}
82
83/// Encode StopAction command (0x04)
84pub fn encode_stop_action(action_id: u16, invoke_id: u32) -> anyhow::Result<Vec<u8>> {
85    let tlv = tlv::TlvItemEnc {
86        tag: 0,
87        value: tlv::TlvItemValueEnc::StructInvisible(vec![
88        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
89        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
90        ]),
91    };
92    Ok(tlv.encode()?)
93}
94
95/// Encode PauseAction command (0x05)
96pub fn encode_pause_action(action_id: u16, invoke_id: u32) -> anyhow::Result<Vec<u8>> {
97    let tlv = tlv::TlvItemEnc {
98        tag: 0,
99        value: tlv::TlvItemValueEnc::StructInvisible(vec![
100        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
101        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
102        ]),
103    };
104    Ok(tlv.encode()?)
105}
106
107/// Encode PauseActionWithDuration command (0x06)
108pub fn encode_pause_action_with_duration(action_id: u16, invoke_id: u32, duration: u32) -> anyhow::Result<Vec<u8>> {
109    let tlv = tlv::TlvItemEnc {
110        tag: 0,
111        value: tlv::TlvItemValueEnc::StructInvisible(vec![
112        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
113        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
114        (2, tlv::TlvItemValueEnc::UInt32(duration)).into(),
115        ]),
116    };
117    Ok(tlv.encode()?)
118}
119
120/// Encode ResumeAction command (0x07)
121pub fn encode_resume_action(action_id: u16, invoke_id: u32) -> anyhow::Result<Vec<u8>> {
122    let tlv = tlv::TlvItemEnc {
123        tag: 0,
124        value: tlv::TlvItemValueEnc::StructInvisible(vec![
125        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
126        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
127        ]),
128    };
129    Ok(tlv.encode()?)
130}
131
132/// Encode EnableAction command (0x08)
133pub fn encode_enable_action(action_id: u16, invoke_id: u32) -> anyhow::Result<Vec<u8>> {
134    let tlv = tlv::TlvItemEnc {
135        tag: 0,
136        value: tlv::TlvItemValueEnc::StructInvisible(vec![
137        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
138        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
139        ]),
140    };
141    Ok(tlv.encode()?)
142}
143
144/// Encode EnableActionWithDuration command (0x09)
145pub fn encode_enable_action_with_duration(action_id: u16, invoke_id: u32, duration: u32) -> anyhow::Result<Vec<u8>> {
146    let tlv = tlv::TlvItemEnc {
147        tag: 0,
148        value: tlv::TlvItemValueEnc::StructInvisible(vec![
149        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
150        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
151        (2, tlv::TlvItemValueEnc::UInt32(duration)).into(),
152        ]),
153    };
154    Ok(tlv.encode()?)
155}
156
157/// Encode DisableAction command (0x0A)
158pub fn encode_disable_action(action_id: u16, invoke_id: u32) -> anyhow::Result<Vec<u8>> {
159    let tlv = tlv::TlvItemEnc {
160        tag: 0,
161        value: tlv::TlvItemValueEnc::StructInvisible(vec![
162        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
163        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
164        ]),
165    };
166    Ok(tlv.encode()?)
167}
168
169/// Encode DisableActionWithDuration command (0x0B)
170pub fn encode_disable_action_with_duration(action_id: u16, invoke_id: u32, duration: u32) -> anyhow::Result<Vec<u8>> {
171    let tlv = tlv::TlvItemEnc {
172        tag: 0,
173        value: tlv::TlvItemValueEnc::StructInvisible(vec![
174        (0, tlv::TlvItemValueEnc::UInt16(action_id)).into(),
175        (1, tlv::TlvItemValueEnc::UInt32(invoke_id)).into(),
176        (2, tlv::TlvItemValueEnc::UInt32(duration)).into(),
177        ]),
178    };
179    Ok(tlv.encode()?)
180}
181
182// Attribute decoders
183
184/// Decode ActionList attribute (0x0000)
185pub fn decode_action_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Action>> {
186    let mut res = Vec::new();
187    if let tlv::TlvItemValue::List(v) = inp {
188        for item in v {
189            res.push(Action {
190                action_id: item.get_int(&[0]).map(|v| v as u16),
191                name: item.get_string_owned(&[1]),
192                type_: item.get_int(&[2]).map(|v| v as u8),
193                endpoint_list_id: item.get_int(&[3]).map(|v| v as u16),
194                supported_commands: item.get_int(&[4]).map(|v| v as u8),
195                state: item.get_int(&[5]).map(|v| v as u8),
196            });
197        }
198    }
199    Ok(res)
200}
201
202/// Decode EndpointLists attribute (0x0001)
203pub fn decode_endpoint_lists(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<EndpointList>> {
204    let mut res = Vec::new();
205    if let tlv::TlvItemValue::List(v) = inp {
206        for item in v {
207            res.push(EndpointList {
208                endpoint_list_id: item.get_int(&[0]).map(|v| v as u16),
209                name: item.get_string_owned(&[1]),
210                type_: item.get_int(&[2]).map(|v| v as u8),
211                endpoints: {
212                    if let Some(tlv::TlvItemValue::List(l)) = item.get(&[3]) {
213                        let items: Vec<u16> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v as u16) } else { None } }).collect();
214                        Some(items)
215                    } else {
216                        None
217                    }
218                },
219            });
220        }
221    }
222    Ok(res)
223}
224
225/// Decode SetupURL attribute (0x0002)
226pub fn decode_setup_url(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
227    if let tlv::TlvItemValue::String(v) = inp {
228        Ok(v.clone())
229    } else {
230        Err(anyhow::anyhow!("Expected String"))
231    }
232}
233
234
235// JSON dispatcher function
236
237/// Decode attribute value and return as JSON string
238/// 
239/// # Parameters
240/// * `cluster_id` - The cluster identifier
241/// * `attribute_id` - The attribute identifier
242/// * `tlv_value` - The TLV value to decode
243/// 
244/// # Returns
245/// JSON string representation of the decoded value or error
246pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
247    // Verify this is the correct cluster
248    if cluster_id != 0x0025 {
249        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0025, got {}\"}}", cluster_id);
250    }
251    
252    match attribute_id {
253        0x0000 => {
254            match decode_action_list(tlv_value) {
255                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
256                Err(e) => format!("{{\"error\": \"{}\"}}", e),
257            }
258        }
259        0x0001 => {
260            match decode_endpoint_lists(tlv_value) {
261                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
262                Err(e) => format!("{{\"error\": \"{}\"}}", e),
263            }
264        }
265        0x0002 => {
266            match decode_setup_url(tlv_value) {
267                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
268                Err(e) => format!("{{\"error\": \"{}\"}}", e),
269            }
270        }
271        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
272    }
273}
274
275/// Get list of all attributes supported by this cluster
276/// 
277/// # Returns
278/// Vector of tuples containing (attribute_id, attribute_name)
279pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
280    vec![
281        (0x0000, "ActionList"),
282        (0x0001, "EndpointLists"),
283        (0x0002, "SetupURL"),
284    ]
285}
286