Skip to main content

matc/clusters/codec/
chime.rs

1//! Matter TLV encoders and decoders for Chime Cluster
2//! Cluster ID: 0x0556
3//!
4//! This file is automatically generated from Chime.xml
5
6#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13// Struct definitions
14
15#[derive(Debug, serde::Serialize)]
16pub struct ChimeSound {
17    pub chime_id: Option<u8>,
18    pub name: Option<String>,
19}
20
21// Command encoders
22
23/// Encode PlayChimeSound command (0x00)
24pub fn encode_play_chime_sound(chime_id: Option<u8>) -> anyhow::Result<Vec<u8>> {
25    let mut tlv_fields: Vec<tlv::TlvItemEnc> = Vec::new();
26    if let Some(x) = chime_id { tlv_fields.push((0, tlv::TlvItemValueEnc::UInt8(x)).into()); }
27    let tlv = tlv::TlvItemEnc {
28        tag: 0,
29        value: tlv::TlvItemValueEnc::StructInvisible(tlv_fields),
30    };
31    Ok(tlv.encode()?)
32}
33
34// Attribute decoders
35
36/// Decode InstalledChimeSounds attribute (0x0000)
37pub fn decode_installed_chime_sounds(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<ChimeSound>> {
38    let mut res = Vec::new();
39    if let tlv::TlvItemValue::List(v) = inp {
40        for item in v {
41            res.push(ChimeSound {
42                chime_id: item.get_int(&[0]).map(|v| v as u8),
43                name: item.get_string_owned(&[1]),
44            });
45        }
46    }
47    Ok(res)
48}
49
50/// Decode SelectedChime attribute (0x0001)
51pub fn decode_selected_chime(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
52    if let tlv::TlvItemValue::Int(v) = inp {
53        Ok(*v as u8)
54    } else {
55        Err(anyhow::anyhow!("Expected UInt8"))
56    }
57}
58
59/// Decode Enabled attribute (0x0002)
60pub fn decode_enabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
61    if let tlv::TlvItemValue::Bool(v) = inp {
62        Ok(*v)
63    } else {
64        Err(anyhow::anyhow!("Expected Bool"))
65    }
66}
67
68
69// JSON dispatcher function
70
71/// Decode attribute value and return as JSON string
72///
73/// # Parameters
74/// * `cluster_id` - The cluster identifier
75/// * `attribute_id` - The attribute identifier
76/// * `tlv_value` - The TLV value to decode
77///
78/// # Returns
79/// JSON string representation of the decoded value or error
80pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
81    // Verify this is the correct cluster
82    if cluster_id != 0x0556 {
83        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0556, got {}\"}}", cluster_id);
84    }
85
86    match attribute_id {
87        0x0000 => {
88            match decode_installed_chime_sounds(tlv_value) {
89                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
90                Err(e) => format!("{{\"error\": \"{}\"}}", e),
91            }
92        }
93        0x0001 => {
94            match decode_selected_chime(tlv_value) {
95                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
96                Err(e) => format!("{{\"error\": \"{}\"}}", e),
97            }
98        }
99        0x0002 => {
100            match decode_enabled(tlv_value) {
101                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
102                Err(e) => format!("{{\"error\": \"{}\"}}", e),
103            }
104        }
105        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
106    }
107}
108
109/// Get list of all attributes supported by this cluster
110///
111/// # Returns
112/// Vector of tuples containing (attribute_id, attribute_name)
113pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
114    vec![
115        (0x0000, "InstalledChimeSounds"),
116        (0x0001, "SelectedChime"),
117        (0x0002, "Enabled"),
118    ]
119}
120
121// Command listing
122
123pub fn get_command_list() -> Vec<(u32, &'static str)> {
124    vec![
125        (0x00, "PlayChimeSound"),
126    ]
127}
128
129pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
130    match cmd_id {
131        0x00 => Some("PlayChimeSound"),
132        _ => None,
133    }
134}
135
136pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
137    match cmd_id {
138        0x00 => Some(vec![
139            crate::clusters::codec::CommandField { tag: 0, name: "chime_id", kind: crate::clusters::codec::FieldKind::U8, optional: true, nullable: false },
140        ]),
141        _ => None,
142    }
143}
144
145pub fn encode_command_json(cmd_id: u32, args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
146    match cmd_id {
147        0x00 => {
148        let chime_id = crate::clusters::codec::json_util::get_opt_u8(args, "chime_id")?;
149        encode_play_chime_sound(chime_id)
150        }
151        _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
152    }
153}
154
155// Typed facade (invokes + reads)
156
157/// Invoke `PlayChimeSound` command on cluster `Chime`.
158pub async fn play_chime_sound(conn: &crate::controller::Connection, endpoint: u16, chime_id: Option<u8>) -> anyhow::Result<()> {
159    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_CHIME, crate::clusters::defs::CLUSTER_CHIME_CMD_ID_PLAYCHIMESOUND, &encode_play_chime_sound(chime_id)?).await?;
160    Ok(())
161}
162
163/// Read `InstalledChimeSounds` attribute from cluster `Chime`.
164pub async fn read_installed_chime_sounds(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<ChimeSound>> {
165    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_CHIME, crate::clusters::defs::CLUSTER_CHIME_ATTR_ID_INSTALLEDCHIMESOUNDS).await?;
166    decode_installed_chime_sounds(&tlv)
167}
168
169/// Read `SelectedChime` attribute from cluster `Chime`.
170pub async fn read_selected_chime(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
171    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_CHIME, crate::clusters::defs::CLUSTER_CHIME_ATTR_ID_SELECTEDCHIME).await?;
172    decode_selected_chime(&tlv)
173}
174
175/// Read `Enabled` attribute from cluster `Chime`.
176pub async fn read_enabled(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
177    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_CHIME, crate::clusters::defs::CLUSTER_CHIME_ATTR_ID_ENABLED).await?;
178    decode_enabled(&tlv)
179}
180
181#[derive(Debug, serde::Serialize)]
182pub struct ChimeStartedPlayingEvent {
183    pub chime_id: Option<u8>,
184}
185
186// Event decoders
187
188/// Decode ChimeStartedPlaying event (0x00, priority: info)
189pub fn decode_chime_started_playing_event(inp: &tlv::TlvItemValue) -> anyhow::Result<ChimeStartedPlayingEvent> {
190    if let tlv::TlvItemValue::List(_fields) = inp {
191        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
192        Ok(ChimeStartedPlayingEvent {
193                                chime_id: item.get_int(&[0]).map(|v| v as u8),
194        })
195    } else {
196        Err(anyhow::anyhow!("Expected struct fields"))
197    }
198}
199
200
201// Event JSON dispatcher
202
203/// Decode event value and return as JSON string
204pub fn decode_event_json(cluster_id: u32, event_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
205    if cluster_id != 0x0556 {
206        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0556, got {}\"}}", cluster_id);
207    }
208
209    match event_id {
210        0x00 => {
211            match decode_chime_started_playing_event(tlv_value) {
212                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
213                Err(e) => format!("{{\"error\": \"{}\"}}", e),
214            }
215        }
216        _ => format!("{{\"error\": \"Unknown event ID: {}\"}}", event_id),
217    }
218}
219
220/// Get list of all events supported by this cluster
221///
222/// # Returns
223/// Vector of tuples containing (event_id, event_name)
224pub fn get_event_list() -> Vec<(u32, &'static str)> {
225    vec![
226        (0x00, "ChimeStartedPlaying"),
227    ]
228}
229