matc/clusters/codec/
scenes.rs

1//! Generated Matter TLV encoders and decoders for Scenes Management Cluster
2//! Cluster ID: 0x0062
3//! 
4//! This file is automatically generated from Scenes.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct AttributeValuePair {
15    pub attribute_id: Option<u8>,
16    pub value_unsigned8: Option<u8>,
17    pub value_signed8: Option<i8>,
18    pub value_unsigned16: Option<u16>,
19    pub value_signed16: Option<i16>,
20    pub value_unsigned32: Option<u32>,
21    pub value_signed32: Option<i32>,
22    pub value_unsigned64: Option<u64>,
23    pub value_signed64: Option<i64>,
24}
25
26#[derive(Debug, serde::Serialize)]
27pub struct ExtensionFieldSet {
28    pub cluster_id: Option<u32>,
29    pub attribute_value_list: Option<Vec<AttributeValuePair>>,
30}
31
32#[derive(Debug, serde::Serialize)]
33pub struct SceneInfo {
34    pub scene_count: Option<u8>,
35    pub current_scene: Option<u8>,
36    pub current_group: Option<u8>,
37    pub scene_valid: Option<bool>,
38    pub remaining_capacity: Option<u8>,
39}
40
41// Command encoders
42
43/// Encode AddScene command (0x00)
44pub fn encode_add_scene(group_id: u8, scene_id: u8, transition_time: u32, scene_name: String, extension_field_set_structs: Vec<u8>) -> anyhow::Result<Vec<u8>> {
45    let tlv = tlv::TlvItemEnc {
46        tag: 0,
47        value: tlv::TlvItemValueEnc::StructInvisible(vec![
48        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
49        (1, tlv::TlvItemValueEnc::UInt8(scene_id)).into(),
50        (2, tlv::TlvItemValueEnc::UInt32(transition_time)).into(),
51        (3, tlv::TlvItemValueEnc::String(scene_name)).into(),
52        (4, tlv::TlvItemValueEnc::StructAnon(extension_field_set_structs.into_iter().map(|v| (0, tlv::TlvItemValueEnc::UInt8(v)).into()).collect())).into(),
53        ]),
54    };
55    Ok(tlv.encode()?)
56}
57
58/// Encode ViewScene command (0x01)
59pub fn encode_view_scene(group_id: u8, scene_id: u8) -> anyhow::Result<Vec<u8>> {
60    let tlv = tlv::TlvItemEnc {
61        tag: 0,
62        value: tlv::TlvItemValueEnc::StructInvisible(vec![
63        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
64        (1, tlv::TlvItemValueEnc::UInt8(scene_id)).into(),
65        ]),
66    };
67    Ok(tlv.encode()?)
68}
69
70/// Encode RemoveScene command (0x02)
71pub fn encode_remove_scene(group_id: u8, scene_id: u8) -> anyhow::Result<Vec<u8>> {
72    let tlv = tlv::TlvItemEnc {
73        tag: 0,
74        value: tlv::TlvItemValueEnc::StructInvisible(vec![
75        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
76        (1, tlv::TlvItemValueEnc::UInt8(scene_id)).into(),
77        ]),
78    };
79    Ok(tlv.encode()?)
80}
81
82/// Encode RemoveAllScenes command (0x03)
83pub fn encode_remove_all_scenes(group_id: u8) -> anyhow::Result<Vec<u8>> {
84    let tlv = tlv::TlvItemEnc {
85        tag: 0,
86        value: tlv::TlvItemValueEnc::StructInvisible(vec![
87        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
88        ]),
89    };
90    Ok(tlv.encode()?)
91}
92
93/// Encode StoreScene command (0x04)
94pub fn encode_store_scene(group_id: u8, scene_id: u8) -> anyhow::Result<Vec<u8>> {
95    let tlv = tlv::TlvItemEnc {
96        tag: 0,
97        value: tlv::TlvItemValueEnc::StructInvisible(vec![
98        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
99        (1, tlv::TlvItemValueEnc::UInt8(scene_id)).into(),
100        ]),
101    };
102    Ok(tlv.encode()?)
103}
104
105/// Encode RecallScene command (0x05)
106pub fn encode_recall_scene(group_id: u8, scene_id: u8, transition_time: Option<u32>) -> anyhow::Result<Vec<u8>> {
107    let tlv = tlv::TlvItemEnc {
108        tag: 0,
109        value: tlv::TlvItemValueEnc::StructInvisible(vec![
110        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
111        (1, tlv::TlvItemValueEnc::UInt8(scene_id)).into(),
112        (2, tlv::TlvItemValueEnc::UInt32(transition_time.unwrap_or(0))).into(),
113        ]),
114    };
115    Ok(tlv.encode()?)
116}
117
118/// Encode GetSceneMembership command (0x06)
119pub fn encode_get_scene_membership(group_id: u8) -> anyhow::Result<Vec<u8>> {
120    let tlv = tlv::TlvItemEnc {
121        tag: 0,
122        value: tlv::TlvItemValueEnc::StructInvisible(vec![
123        (0, tlv::TlvItemValueEnc::UInt8(group_id)).into(),
124        ]),
125    };
126    Ok(tlv.encode()?)
127}
128
129/// Encode CopyScene command (0x40)
130pub fn encode_copy_scene(mode: u8, group_identifier_from: u8, scene_identifier_from: u8, group_identifier_to: u8, scene_identifier_to: u8) -> anyhow::Result<Vec<u8>> {
131    let tlv = tlv::TlvItemEnc {
132        tag: 0,
133        value: tlv::TlvItemValueEnc::StructInvisible(vec![
134        (0, tlv::TlvItemValueEnc::UInt8(mode)).into(),
135        (1, tlv::TlvItemValueEnc::UInt8(group_identifier_from)).into(),
136        (2, tlv::TlvItemValueEnc::UInt8(scene_identifier_from)).into(),
137        (3, tlv::TlvItemValueEnc::UInt8(group_identifier_to)).into(),
138        (4, tlv::TlvItemValueEnc::UInt8(scene_identifier_to)).into(),
139        ]),
140    };
141    Ok(tlv.encode()?)
142}
143
144// Attribute decoders
145
146/// Decode DoNotUse attribute (0x0000)
147pub fn decode_do_not_use(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 Integer"))
152    }
153}
154
155/// Decode SceneTableSize attribute (0x0001)
156pub fn decode_scene_table_size(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
157    if let tlv::TlvItemValue::Int(v) = inp {
158        Ok(*v as u16)
159    } else {
160        Err(anyhow::anyhow!("Expected Integer"))
161    }
162}
163
164/// Decode FabricSceneInfo attribute (0x0002)
165pub fn decode_fabric_scene_info(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<SceneInfo>> {
166    let mut res = Vec::new();
167    if let tlv::TlvItemValue::List(v) = inp {
168        for item in v {
169            res.push(SceneInfo {
170                scene_count: item.get_int(&[0]).map(|v| v as u8),
171                current_scene: item.get_int(&[1]).map(|v| v as u8),
172                current_group: item.get_int(&[2]).map(|v| v as u8),
173                scene_valid: item.get_bool(&[3]),
174                remaining_capacity: item.get_int(&[4]).map(|v| v as u8),
175            });
176        }
177    }
178    Ok(res)
179}
180
181
182// JSON dispatcher function
183
184/// Decode attribute value and return as JSON string
185/// 
186/// # Parameters
187/// * `cluster_id` - The cluster identifier
188/// * `attribute_id` - The attribute identifier
189/// * `tlv_value` - The TLV value to decode
190/// 
191/// # Returns
192/// JSON string representation of the decoded value or error
193pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
194    // Verify this is the correct cluster
195    if cluster_id != 0x0062 {
196        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0062, got {}\"}}", cluster_id);
197    }
198    
199    match attribute_id {
200        0x0000 => {
201            match decode_do_not_use(tlv_value) {
202                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
203                Err(e) => format!("{{\"error\": \"{}\"}}", e),
204            }
205        }
206        0x0001 => {
207            match decode_scene_table_size(tlv_value) {
208                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
209                Err(e) => format!("{{\"error\": \"{}\"}}", e),
210            }
211        }
212        0x0002 => {
213            match decode_fabric_scene_info(tlv_value) {
214                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
215                Err(e) => format!("{{\"error\": \"{}\"}}", e),
216            }
217        }
218        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
219    }
220}
221
222/// Get list of all attributes supported by this cluster
223/// 
224/// # Returns
225/// Vector of tuples containing (attribute_id, attribute_name)
226pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
227    vec![
228        (0x0000, "DoNotUse"),
229        (0x0001, "SceneTableSize"),
230        (0x0002, "FabricSceneInfo"),
231    ]
232}
233