1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11pub fn encode_move_to_level(level: u8, transition_time: Option<u16>, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
15 let tlv = tlv::TlvItemEnc {
16 tag: 0,
17 value: tlv::TlvItemValueEnc::StructInvisible(vec![
18 (0, tlv::TlvItemValueEnc::UInt8(level)).into(),
19 (1, tlv::TlvItemValueEnc::UInt16(transition_time.unwrap_or(0))).into(),
20 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
21 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
22 ]),
23 };
24 Ok(tlv.encode()?)
25}
26
27pub fn encode_move_(move_mode: u8, rate: Option<u8>, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
29 let tlv = tlv::TlvItemEnc {
30 tag: 0,
31 value: tlv::TlvItemValueEnc::StructInvisible(vec![
32 (0, tlv::TlvItemValueEnc::UInt8(move_mode)).into(),
33 (1, tlv::TlvItemValueEnc::UInt8(rate.unwrap_or(0))).into(),
34 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
35 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
36 ]),
37 };
38 Ok(tlv.encode()?)
39}
40
41pub fn encode_step(step_mode: u8, step_size: u8, transition_time: Option<u16>, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
43 let tlv = tlv::TlvItemEnc {
44 tag: 0,
45 value: tlv::TlvItemValueEnc::StructInvisible(vec![
46 (0, tlv::TlvItemValueEnc::UInt8(step_mode)).into(),
47 (1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
48 (2, tlv::TlvItemValueEnc::UInt16(transition_time.unwrap_or(0))).into(),
49 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
50 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
51 ]),
52 };
53 Ok(tlv.encode()?)
54}
55
56pub fn encode_stop(options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
58 let tlv = tlv::TlvItemEnc {
59 tag: 0,
60 value: tlv::TlvItemValueEnc::StructInvisible(vec![
61 (0, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
62 (1, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
63 ]),
64 };
65 Ok(tlv.encode()?)
66}
67
68pub fn encode_move_to_level_with_on_off(level: u8, transition_time: Option<u16>, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
70 let tlv = tlv::TlvItemEnc {
71 tag: 0,
72 value: tlv::TlvItemValueEnc::StructInvisible(vec![
73 (0, tlv::TlvItemValueEnc::UInt8(level)).into(),
74 (1, tlv::TlvItemValueEnc::UInt16(transition_time.unwrap_or(0))).into(),
75 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
76 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
77 ]),
78 };
79 Ok(tlv.encode()?)
80}
81
82pub fn encode_move_with_on_off(move_mode: u8, rate: Option<u8>, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
84 let tlv = tlv::TlvItemEnc {
85 tag: 0,
86 value: tlv::TlvItemValueEnc::StructInvisible(vec![
87 (0, tlv::TlvItemValueEnc::UInt8(move_mode)).into(),
88 (1, tlv::TlvItemValueEnc::UInt8(rate.unwrap_or(0))).into(),
89 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
90 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
91 ]),
92 };
93 Ok(tlv.encode()?)
94}
95
96pub fn encode_step_with_on_off(step_mode: u8, step_size: u8, transition_time: Option<u16>, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
98 let tlv = tlv::TlvItemEnc {
99 tag: 0,
100 value: tlv::TlvItemValueEnc::StructInvisible(vec![
101 (0, tlv::TlvItemValueEnc::UInt8(step_mode)).into(),
102 (1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
103 (2, tlv::TlvItemValueEnc::UInt16(transition_time.unwrap_or(0))).into(),
104 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
105 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
106 ]),
107 };
108 Ok(tlv.encode()?)
109}
110
111pub fn encode_stop_with_on_off(options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
113 let tlv = tlv::TlvItemEnc {
114 tag: 0,
115 value: tlv::TlvItemValueEnc::StructInvisible(vec![
116 (0, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
117 (1, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
118 ]),
119 };
120 Ok(tlv.encode()?)
121}
122
123pub fn encode_move_to_closest_frequency(frequency: u16) -> anyhow::Result<Vec<u8>> {
125 let tlv = tlv::TlvItemEnc {
126 tag: 0,
127 value: tlv::TlvItemValueEnc::StructInvisible(vec![
128 (0, tlv::TlvItemValueEnc::UInt16(frequency)).into(),
129 ]),
130 };
131 Ok(tlv.encode()?)
132}
133
134pub fn decode_current_level(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
138 if let tlv::TlvItemValue::Int(v) = inp {
139 Ok(Some(*v as u8))
140 } else {
141 Ok(None)
142 }
143}
144
145pub fn decode_remaining_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
147 if let tlv::TlvItemValue::Int(v) = inp {
148 Ok(*v as u16)
149 } else {
150 Err(anyhow::anyhow!("Expected Integer"))
151 }
152}
153
154pub fn decode_min_level(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
156 if let tlv::TlvItemValue::Int(v) = inp {
157 Ok(*v as u8)
158 } else {
159 Err(anyhow::anyhow!("Expected Integer"))
160 }
161}
162
163pub fn decode_max_level(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
165 if let tlv::TlvItemValue::Int(v) = inp {
166 Ok(*v as u8)
167 } else {
168 Err(anyhow::anyhow!("Expected Integer"))
169 }
170}
171
172pub fn decode_current_frequency(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
174 if let tlv::TlvItemValue::Int(v) = inp {
175 Ok(*v as u16)
176 } else {
177 Err(anyhow::anyhow!("Expected Integer"))
178 }
179}
180
181pub fn decode_min_frequency(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
183 if let tlv::TlvItemValue::Int(v) = inp {
184 Ok(*v as u16)
185 } else {
186 Err(anyhow::anyhow!("Expected Integer"))
187 }
188}
189
190pub fn decode_max_frequency(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
192 if let tlv::TlvItemValue::Int(v) = inp {
193 Ok(*v as u16)
194 } else {
195 Err(anyhow::anyhow!("Expected Integer"))
196 }
197}
198
199pub fn decode_options(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
201 if let tlv::TlvItemValue::Int(v) = inp {
202 Ok(*v as u8)
203 } else {
204 Err(anyhow::anyhow!("Expected Integer"))
205 }
206}
207
208pub fn decode_on_off_transition_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
210 if let tlv::TlvItemValue::Int(v) = inp {
211 Ok(*v as u16)
212 } else {
213 Err(anyhow::anyhow!("Expected Integer"))
214 }
215}
216
217pub fn decode_on_level(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
219 if let tlv::TlvItemValue::Int(v) = inp {
220 Ok(Some(*v as u8))
221 } else {
222 Ok(None)
223 }
224}
225
226pub fn decode_on_transition_time(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
228 if let tlv::TlvItemValue::Int(v) = inp {
229 Ok(Some(*v as u16))
230 } else {
231 Ok(None)
232 }
233}
234
235pub fn decode_off_transition_time(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
237 if let tlv::TlvItemValue::Int(v) = inp {
238 Ok(Some(*v as u16))
239 } else {
240 Ok(None)
241 }
242}
243
244pub fn decode_default_move_rate(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
246 if let tlv::TlvItemValue::Int(v) = inp {
247 Ok(Some(*v as u8))
248 } else {
249 Ok(None)
250 }
251}
252
253pub fn decode_start_up_current_level(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
255 if let tlv::TlvItemValue::Int(v) = inp {
256 Ok(Some(*v as u8))
257 } else {
258 Ok(None)
259 }
260}
261
262
263pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
275 if cluster_id != 0x0008 {
277 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0008, got {}\"}}", cluster_id);
278 }
279
280 match attribute_id {
281 0x0000 => {
282 match decode_current_level(tlv_value) {
283 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
284 Err(e) => format!("{{\"error\": \"{}\"}}", e),
285 }
286 }
287 0x0001 => {
288 match decode_remaining_time(tlv_value) {
289 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
290 Err(e) => format!("{{\"error\": \"{}\"}}", e),
291 }
292 }
293 0x0002 => {
294 match decode_min_level(tlv_value) {
295 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
296 Err(e) => format!("{{\"error\": \"{}\"}}", e),
297 }
298 }
299 0x0003 => {
300 match decode_max_level(tlv_value) {
301 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
302 Err(e) => format!("{{\"error\": \"{}\"}}", e),
303 }
304 }
305 0x0004 => {
306 match decode_current_frequency(tlv_value) {
307 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
308 Err(e) => format!("{{\"error\": \"{}\"}}", e),
309 }
310 }
311 0x0005 => {
312 match decode_min_frequency(tlv_value) {
313 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
314 Err(e) => format!("{{\"error\": \"{}\"}}", e),
315 }
316 }
317 0x0006 => {
318 match decode_max_frequency(tlv_value) {
319 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
320 Err(e) => format!("{{\"error\": \"{}\"}}", e),
321 }
322 }
323 0x000F => {
324 match decode_options(tlv_value) {
325 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
326 Err(e) => format!("{{\"error\": \"{}\"}}", e),
327 }
328 }
329 0x0010 => {
330 match decode_on_off_transition_time(tlv_value) {
331 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
332 Err(e) => format!("{{\"error\": \"{}\"}}", e),
333 }
334 }
335 0x0011 => {
336 match decode_on_level(tlv_value) {
337 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
338 Err(e) => format!("{{\"error\": \"{}\"}}", e),
339 }
340 }
341 0x0012 => {
342 match decode_on_transition_time(tlv_value) {
343 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
344 Err(e) => format!("{{\"error\": \"{}\"}}", e),
345 }
346 }
347 0x0013 => {
348 match decode_off_transition_time(tlv_value) {
349 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
350 Err(e) => format!("{{\"error\": \"{}\"}}", e),
351 }
352 }
353 0x0014 => {
354 match decode_default_move_rate(tlv_value) {
355 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
356 Err(e) => format!("{{\"error\": \"{}\"}}", e),
357 }
358 }
359 0x4000 => {
360 match decode_start_up_current_level(tlv_value) {
361 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
362 Err(e) => format!("{{\"error\": \"{}\"}}", e),
363 }
364 }
365 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
366 }
367}
368
369pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
374 vec![
375 (0x0000, "CurrentLevel"),
376 (0x0001, "RemainingTime"),
377 (0x0002, "MinLevel"),
378 (0x0003, "MaxLevel"),
379 (0x0004, "CurrentFrequency"),
380 (0x0005, "MinFrequency"),
381 (0x0006, "MaxFrequency"),
382 (0x000F, "Options"),
383 (0x0010, "OnOffTransitionTime"),
384 (0x0011, "OnLevel"),
385 (0x0012, "OnTransitionTime"),
386 (0x0013, "OffTransitionTime"),
387 (0x0014, "DefaultMoveRate"),
388 (0x4000, "StartUpCurrentLevel"),
389 ]
390}
391