matc/clusters/codec/
switch.rs1#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13pub fn decode_number_of_positions(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
17 if let tlv::TlvItemValue::Int(v) = inp {
18 Ok(*v as u8)
19 } else {
20 Err(anyhow::anyhow!("Expected UInt8"))
21 }
22}
23
24pub fn decode_current_position(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
26 if let tlv::TlvItemValue::Int(v) = inp {
27 Ok(*v as u8)
28 } else {
29 Err(anyhow::anyhow!("Expected UInt8"))
30 }
31}
32
33pub fn decode_multi_press_max(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
35 if let tlv::TlvItemValue::Int(v) = inp {
36 Ok(*v as u8)
37 } else {
38 Err(anyhow::anyhow!("Expected UInt8"))
39 }
40}
41
42
43pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
55 if cluster_id != 0x003B {
57 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x003B, got {}\"}}", cluster_id);
58 }
59
60 match attribute_id {
61 0x0000 => {
62 match decode_number_of_positions(tlv_value) {
63 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
64 Err(e) => format!("{{\"error\": \"{}\"}}", e),
65 }
66 }
67 0x0001 => {
68 match decode_current_position(tlv_value) {
69 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
70 Err(e) => format!("{{\"error\": \"{}\"}}", e),
71 }
72 }
73 0x0002 => {
74 match decode_multi_press_max(tlv_value) {
75 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
76 Err(e) => format!("{{\"error\": \"{}\"}}", e),
77 }
78 }
79 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
80 }
81}
82
83pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
88 vec![
89 (0x0000, "NumberOfPositions"),
90 (0x0001, "CurrentPosition"),
91 (0x0002, "MultiPressMax"),
92 ]
93}
94
95pub async fn read_number_of_positions(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
99 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_SWITCH, crate::clusters::defs::CLUSTER_SWITCH_ATTR_ID_NUMBEROFPOSITIONS).await?;
100 decode_number_of_positions(&tlv)
101}
102
103pub async fn read_current_position(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
105 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_SWITCH, crate::clusters::defs::CLUSTER_SWITCH_ATTR_ID_CURRENTPOSITION).await?;
106 decode_current_position(&tlv)
107}
108
109pub async fn read_multi_press_max(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
111 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_SWITCH, crate::clusters::defs::CLUSTER_SWITCH_ATTR_ID_MULTIPRESSMAX).await?;
112 decode_multi_press_max(&tlv)
113}
114
115#[derive(Debug, serde::Serialize)]
116pub struct SwitchLatchedEvent {
117 pub new_position: Option<u8>,
118}
119
120#[derive(Debug, serde::Serialize)]
121pub struct InitialPressEvent {
122 pub new_position: Option<u8>,
123}
124
125#[derive(Debug, serde::Serialize)]
126pub struct LongPressEvent {
127 pub new_position: Option<u8>,
128}
129
130#[derive(Debug, serde::Serialize)]
131pub struct ShortReleaseEvent {
132 pub previous_position: Option<u8>,
133}
134
135#[derive(Debug, serde::Serialize)]
136pub struct LongReleaseEvent {
137 pub previous_position: Option<u8>,
138}
139
140#[derive(Debug, serde::Serialize)]
141pub struct MultiPressOngoingEvent {
142 pub new_position: Option<u8>,
143 pub current_number_of_presses_counted: Option<u8>,
144}
145
146#[derive(Debug, serde::Serialize)]
147pub struct MultiPressCompleteEvent {
148 pub previous_position: Option<u8>,
149 pub total_number_of_presses_counted: Option<u8>,
150}
151
152pub fn decode_switch_latched_event(inp: &tlv::TlvItemValue) -> anyhow::Result<SwitchLatchedEvent> {
156 if let tlv::TlvItemValue::List(_fields) = inp {
157 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
158 Ok(SwitchLatchedEvent {
159 new_position: item.get_int(&[0]).map(|v| v as u8),
160 })
161 } else {
162 Err(anyhow::anyhow!("Expected struct fields"))
163 }
164}
165
166pub fn decode_initial_press_event(inp: &tlv::TlvItemValue) -> anyhow::Result<InitialPressEvent> {
168 if let tlv::TlvItemValue::List(_fields) = inp {
169 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
170 Ok(InitialPressEvent {
171 new_position: item.get_int(&[0]).map(|v| v as u8),
172 })
173 } else {
174 Err(anyhow::anyhow!("Expected struct fields"))
175 }
176}
177
178pub fn decode_long_press_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LongPressEvent> {
180 if let tlv::TlvItemValue::List(_fields) = inp {
181 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
182 Ok(LongPressEvent {
183 new_position: item.get_int(&[0]).map(|v| v as u8),
184 })
185 } else {
186 Err(anyhow::anyhow!("Expected struct fields"))
187 }
188}
189
190pub fn decode_short_release_event(inp: &tlv::TlvItemValue) -> anyhow::Result<ShortReleaseEvent> {
192 if let tlv::TlvItemValue::List(_fields) = inp {
193 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
194 Ok(ShortReleaseEvent {
195 previous_position: item.get_int(&[0]).map(|v| v as u8),
196 })
197 } else {
198 Err(anyhow::anyhow!("Expected struct fields"))
199 }
200}
201
202pub fn decode_long_release_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LongReleaseEvent> {
204 if let tlv::TlvItemValue::List(_fields) = inp {
205 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
206 Ok(LongReleaseEvent {
207 previous_position: item.get_int(&[0]).map(|v| v as u8),
208 })
209 } else {
210 Err(anyhow::anyhow!("Expected struct fields"))
211 }
212}
213
214pub fn decode_multi_press_ongoing_event(inp: &tlv::TlvItemValue) -> anyhow::Result<MultiPressOngoingEvent> {
216 if let tlv::TlvItemValue::List(_fields) = inp {
217 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
218 Ok(MultiPressOngoingEvent {
219 new_position: item.get_int(&[0]).map(|v| v as u8),
220 current_number_of_presses_counted: item.get_int(&[1]).map(|v| v as u8),
221 })
222 } else {
223 Err(anyhow::anyhow!("Expected struct fields"))
224 }
225}
226
227pub fn decode_multi_press_complete_event(inp: &tlv::TlvItemValue) -> anyhow::Result<MultiPressCompleteEvent> {
229 if let tlv::TlvItemValue::List(_fields) = inp {
230 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
231 Ok(MultiPressCompleteEvent {
232 previous_position: item.get_int(&[0]).map(|v| v as u8),
233 total_number_of_presses_counted: item.get_int(&[1]).map(|v| v as u8),
234 })
235 } else {
236 Err(anyhow::anyhow!("Expected struct fields"))
237 }
238}
239