1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11pub fn encode_move_to_hue(hue: u8, direction: u8, transition_time: 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(hue)).into(),
19 (1, tlv::TlvItemValueEnc::UInt8(direction)).into(),
20 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
21 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
22 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
23 ]),
24 };
25 Ok(tlv.encode()?)
26}
27
28pub fn encode_move_hue(move_mode: u8, rate: u8, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
30 let tlv = tlv::TlvItemEnc {
31 tag: 0,
32 value: tlv::TlvItemValueEnc::StructInvisible(vec![
33 (0, tlv::TlvItemValueEnc::UInt8(move_mode)).into(),
34 (1, tlv::TlvItemValueEnc::UInt8(rate)).into(),
35 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
36 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
37 ]),
38 };
39 Ok(tlv.encode()?)
40}
41
42pub fn encode_step_hue(step_mode: u8, step_size: u8, transition_time: u8, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
44 let tlv = tlv::TlvItemEnc {
45 tag: 0,
46 value: tlv::TlvItemValueEnc::StructInvisible(vec![
47 (0, tlv::TlvItemValueEnc::UInt8(step_mode)).into(),
48 (1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
49 (2, tlv::TlvItemValueEnc::UInt8(transition_time)).into(),
50 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
51 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
52 ]),
53 };
54 Ok(tlv.encode()?)
55}
56
57pub fn encode_move_to_saturation(saturation: u8, transition_time: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
59 let tlv = tlv::TlvItemEnc {
60 tag: 0,
61 value: tlv::TlvItemValueEnc::StructInvisible(vec![
62 (0, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
63 (1, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
64 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
65 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
66 ]),
67 };
68 Ok(tlv.encode()?)
69}
70
71pub fn encode_move_saturation(move_mode: u8, rate: u8, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
73 let tlv = tlv::TlvItemEnc {
74 tag: 0,
75 value: tlv::TlvItemValueEnc::StructInvisible(vec![
76 (0, tlv::TlvItemValueEnc::UInt8(move_mode)).into(),
77 (1, tlv::TlvItemValueEnc::UInt8(rate)).into(),
78 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
79 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
80 ]),
81 };
82 Ok(tlv.encode()?)
83}
84
85pub fn encode_step_saturation(step_mode: u8, step_size: u8, transition_time: u8, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
87 let tlv = tlv::TlvItemEnc {
88 tag: 0,
89 value: tlv::TlvItemValueEnc::StructInvisible(vec![
90 (0, tlv::TlvItemValueEnc::UInt8(step_mode)).into(),
91 (1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
92 (2, tlv::TlvItemValueEnc::UInt8(transition_time)).into(),
93 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
94 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
95 ]),
96 };
97 Ok(tlv.encode()?)
98}
99
100pub fn encode_move_to_hue_and_saturation(hue: u8, saturation: u8, transition_time: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
102 let tlv = tlv::TlvItemEnc {
103 tag: 0,
104 value: tlv::TlvItemValueEnc::StructInvisible(vec![
105 (0, tlv::TlvItemValueEnc::UInt8(hue)).into(),
106 (1, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
107 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
108 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
109 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
110 ]),
111 };
112 Ok(tlv.encode()?)
113}
114
115pub fn encode_move_to_color(color_x: u16, color_y: u16, transition_time: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
117 let tlv = tlv::TlvItemEnc {
118 tag: 0,
119 value: tlv::TlvItemValueEnc::StructInvisible(vec![
120 (0, tlv::TlvItemValueEnc::UInt16(color_x)).into(),
121 (1, tlv::TlvItemValueEnc::UInt16(color_y)).into(),
122 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
123 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
124 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
125 ]),
126 };
127 Ok(tlv.encode()?)
128}
129
130pub fn encode_move_color(rate_x: i16, rate_y: i16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
132 let tlv = tlv::TlvItemEnc {
133 tag: 0,
134 value: tlv::TlvItemValueEnc::StructInvisible(vec![
135 (0, tlv::TlvItemValueEnc::Int16(rate_x)).into(),
136 (1, tlv::TlvItemValueEnc::Int16(rate_y)).into(),
137 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
138 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
139 ]),
140 };
141 Ok(tlv.encode()?)
142}
143
144pub fn encode_step_color(step_x: i16, step_y: i16, transition_time: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
146 let tlv = tlv::TlvItemEnc {
147 tag: 0,
148 value: tlv::TlvItemValueEnc::StructInvisible(vec![
149 (0, tlv::TlvItemValueEnc::Int16(step_x)).into(),
150 (1, tlv::TlvItemValueEnc::Int16(step_y)).into(),
151 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
152 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
153 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
154 ]),
155 };
156 Ok(tlv.encode()?)
157}
158
159pub fn encode_move_to_color_temperature(color_temperature_mireds: u16, transition_time: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
161 let tlv = tlv::TlvItemEnc {
162 tag: 0,
163 value: tlv::TlvItemValueEnc::StructInvisible(vec![
164 (0, tlv::TlvItemValueEnc::UInt16(color_temperature_mireds)).into(),
165 (1, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
166 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
167 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
168 ]),
169 };
170 Ok(tlv.encode()?)
171}
172
173pub fn encode_enhanced_move_to_hue(enhanced_hue: u16, direction: u8, transition_time: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
175 let tlv = tlv::TlvItemEnc {
176 tag: 0,
177 value: tlv::TlvItemValueEnc::StructInvisible(vec![
178 (0, tlv::TlvItemValueEnc::UInt16(enhanced_hue)).into(),
179 (1, tlv::TlvItemValueEnc::UInt8(direction)).into(),
180 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
181 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
182 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
183 ]),
184 };
185 Ok(tlv.encode()?)
186}
187
188pub fn encode_enhanced_move_hue(move_mode: u8, rate: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
190 let tlv = tlv::TlvItemEnc {
191 tag: 0,
192 value: tlv::TlvItemValueEnc::StructInvisible(vec![
193 (0, tlv::TlvItemValueEnc::UInt8(move_mode)).into(),
194 (1, tlv::TlvItemValueEnc::UInt16(rate)).into(),
195 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
196 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
197 ]),
198 };
199 Ok(tlv.encode()?)
200}
201
202pub fn encode_enhanced_step_hue(step_mode: u8, step_size: u16, transition_time: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
204 let tlv = tlv::TlvItemEnc {
205 tag: 0,
206 value: tlv::TlvItemValueEnc::StructInvisible(vec![
207 (0, tlv::TlvItemValueEnc::UInt8(step_mode)).into(),
208 (1, tlv::TlvItemValueEnc::UInt16(step_size)).into(),
209 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
210 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
211 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
212 ]),
213 };
214 Ok(tlv.encode()?)
215}
216
217pub fn encode_enhanced_move_to_hue_and_saturation(enhanced_hue: u16, saturation: u8, transition_time: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
219 let tlv = tlv::TlvItemEnc {
220 tag: 0,
221 value: tlv::TlvItemValueEnc::StructInvisible(vec![
222 (0, tlv::TlvItemValueEnc::UInt16(enhanced_hue)).into(),
223 (1, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
224 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
225 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
226 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
227 ]),
228 };
229 Ok(tlv.encode()?)
230}
231
232pub fn encode_color_loop_set(update_flags: u8, action: u8, direction: u8, time: u16, start_hue: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
234 let tlv = tlv::TlvItemEnc {
235 tag: 0,
236 value: tlv::TlvItemValueEnc::StructInvisible(vec![
237 (0, tlv::TlvItemValueEnc::UInt8(update_flags)).into(),
238 (1, tlv::TlvItemValueEnc::UInt8(action)).into(),
239 (2, tlv::TlvItemValueEnc::UInt8(direction)).into(),
240 (3, tlv::TlvItemValueEnc::UInt16(time)).into(),
241 (4, tlv::TlvItemValueEnc::UInt16(start_hue)).into(),
242 (5, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
243 (6, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
244 ]),
245 };
246 Ok(tlv.encode()?)
247}
248
249pub fn encode_stop_move_step(options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
251 let tlv = tlv::TlvItemEnc {
252 tag: 0,
253 value: tlv::TlvItemValueEnc::StructInvisible(vec![
254 (0, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
255 (1, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
256 ]),
257 };
258 Ok(tlv.encode()?)
259}
260
261pub fn encode_move_color_temperature(move_mode: u8, rate: u16, color_temperature_minimum_mireds: u16, color_temperature_maximum_mireds: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
263 let tlv = tlv::TlvItemEnc {
264 tag: 0,
265 value: tlv::TlvItemValueEnc::StructInvisible(vec![
266 (0, tlv::TlvItemValueEnc::UInt8(move_mode)).into(),
267 (1, tlv::TlvItemValueEnc::UInt16(rate)).into(),
268 (2, tlv::TlvItemValueEnc::UInt16(color_temperature_minimum_mireds)).into(),
269 (3, tlv::TlvItemValueEnc::UInt16(color_temperature_maximum_mireds)).into(),
270 (4, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
271 (5, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
272 ]),
273 };
274 Ok(tlv.encode()?)
275}
276
277pub fn encode_step_color_temperature(step_mode: u8, step_size: u16, transition_time: u16, color_temperature_minimum_mireds: u16, color_temperature_maximum_mireds: u16, options_mask: u8, options_override: u8) -> anyhow::Result<Vec<u8>> {
279 let tlv = tlv::TlvItemEnc {
280 tag: 0,
281 value: tlv::TlvItemValueEnc::StructInvisible(vec![
282 (0, tlv::TlvItemValueEnc::UInt8(step_mode)).into(),
283 (1, tlv::TlvItemValueEnc::UInt16(step_size)).into(),
284 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
285 (3, tlv::TlvItemValueEnc::UInt16(color_temperature_minimum_mireds)).into(),
286 (4, tlv::TlvItemValueEnc::UInt16(color_temperature_maximum_mireds)).into(),
287 (5, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
288 (6, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
289 ]),
290 };
291 Ok(tlv.encode()?)
292}
293
294pub fn decode_current_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
298 if let tlv::TlvItemValue::Int(v) = inp {
299 Ok(*v as u8)
300 } else {
301 Err(anyhow::anyhow!("Expected Integer"))
302 }
303}
304
305pub fn decode_current_saturation(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
307 if let tlv::TlvItemValue::Int(v) = inp {
308 Ok(*v as u8)
309 } else {
310 Err(anyhow::anyhow!("Expected Integer"))
311 }
312}
313
314pub fn decode_remaining_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
316 if let tlv::TlvItemValue::Int(v) = inp {
317 Ok(*v as u16)
318 } else {
319 Err(anyhow::anyhow!("Expected Integer"))
320 }
321}
322
323pub fn decode_current_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
325 if let tlv::TlvItemValue::Int(v) = inp {
326 Ok(*v as u16)
327 } else {
328 Err(anyhow::anyhow!("Expected Integer"))
329 }
330}
331
332pub fn decode_current_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
334 if let tlv::TlvItemValue::Int(v) = inp {
335 Ok(*v as u16)
336 } else {
337 Err(anyhow::anyhow!("Expected Integer"))
338 }
339}
340
341pub fn decode_drift_compensation(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
343 if let tlv::TlvItemValue::Int(v) = inp {
344 Ok(*v as u8)
345 } else {
346 Err(anyhow::anyhow!("Expected Integer"))
347 }
348}
349
350pub fn decode_compensation_text(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
352 if let tlv::TlvItemValue::String(v) = inp {
353 Ok(v.clone())
354 } else {
355 Err(anyhow::anyhow!("Expected String"))
356 }
357}
358
359pub fn decode_color_temperature_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
361 if let tlv::TlvItemValue::Int(v) = inp {
362 Ok(*v as u16)
363 } else {
364 Err(anyhow::anyhow!("Expected Integer"))
365 }
366}
367
368pub fn decode_color_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
370 if let tlv::TlvItemValue::Int(v) = inp {
371 Ok(*v as u8)
372 } else {
373 Err(anyhow::anyhow!("Expected Integer"))
374 }
375}
376
377pub fn decode_options(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
379 if let tlv::TlvItemValue::Int(v) = inp {
380 Ok(*v as u8)
381 } else {
382 Err(anyhow::anyhow!("Expected Integer"))
383 }
384}
385
386pub fn decode_number_of_primaries(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
388 if let tlv::TlvItemValue::Int(v) = inp {
389 Ok(Some(*v as u8))
390 } else {
391 Ok(None)
392 }
393}
394
395pub fn decode_primary1_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
397 if let tlv::TlvItemValue::Int(v) = inp {
398 Ok(*v as u16)
399 } else {
400 Err(anyhow::anyhow!("Expected Integer"))
401 }
402}
403
404pub fn decode_primary1_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
406 if let tlv::TlvItemValue::Int(v) = inp {
407 Ok(*v as u16)
408 } else {
409 Err(anyhow::anyhow!("Expected Integer"))
410 }
411}
412
413pub fn decode_primary1_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
415 if let tlv::TlvItemValue::Int(v) = inp {
416 Ok(Some(*v as u8))
417 } else {
418 Ok(None)
419 }
420}
421
422pub fn decode_primary2_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
424 if let tlv::TlvItemValue::Int(v) = inp {
425 Ok(*v as u16)
426 } else {
427 Err(anyhow::anyhow!("Expected Integer"))
428 }
429}
430
431pub fn decode_primary2_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
433 if let tlv::TlvItemValue::Int(v) = inp {
434 Ok(*v as u16)
435 } else {
436 Err(anyhow::anyhow!("Expected Integer"))
437 }
438}
439
440pub fn decode_primary2_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
442 if let tlv::TlvItemValue::Int(v) = inp {
443 Ok(Some(*v as u8))
444 } else {
445 Ok(None)
446 }
447}
448
449pub fn decode_primary3_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
451 if let tlv::TlvItemValue::Int(v) = inp {
452 Ok(*v as u16)
453 } else {
454 Err(anyhow::anyhow!("Expected Integer"))
455 }
456}
457
458pub fn decode_primary3_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
460 if let tlv::TlvItemValue::Int(v) = inp {
461 Ok(*v as u16)
462 } else {
463 Err(anyhow::anyhow!("Expected Integer"))
464 }
465}
466
467pub fn decode_primary3_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
469 if let tlv::TlvItemValue::Int(v) = inp {
470 Ok(Some(*v as u8))
471 } else {
472 Ok(None)
473 }
474}
475
476pub fn decode_primary4_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
478 if let tlv::TlvItemValue::Int(v) = inp {
479 Ok(*v as u16)
480 } else {
481 Err(anyhow::anyhow!("Expected Integer"))
482 }
483}
484
485pub fn decode_primary4_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
487 if let tlv::TlvItemValue::Int(v) = inp {
488 Ok(*v as u16)
489 } else {
490 Err(anyhow::anyhow!("Expected Integer"))
491 }
492}
493
494pub fn decode_primary4_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
496 if let tlv::TlvItemValue::Int(v) = inp {
497 Ok(Some(*v as u8))
498 } else {
499 Ok(None)
500 }
501}
502
503pub fn decode_primary5_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
505 if let tlv::TlvItemValue::Int(v) = inp {
506 Ok(*v as u16)
507 } else {
508 Err(anyhow::anyhow!("Expected Integer"))
509 }
510}
511
512pub fn decode_primary5_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
514 if let tlv::TlvItemValue::Int(v) = inp {
515 Ok(*v as u16)
516 } else {
517 Err(anyhow::anyhow!("Expected Integer"))
518 }
519}
520
521pub fn decode_primary5_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
523 if let tlv::TlvItemValue::Int(v) = inp {
524 Ok(Some(*v as u8))
525 } else {
526 Ok(None)
527 }
528}
529
530pub fn decode_primary6_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
532 if let tlv::TlvItemValue::Int(v) = inp {
533 Ok(*v as u16)
534 } else {
535 Err(anyhow::anyhow!("Expected Integer"))
536 }
537}
538
539pub fn decode_primary6_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
541 if let tlv::TlvItemValue::Int(v) = inp {
542 Ok(*v as u16)
543 } else {
544 Err(anyhow::anyhow!("Expected Integer"))
545 }
546}
547
548pub fn decode_primary6_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
550 if let tlv::TlvItemValue::Int(v) = inp {
551 Ok(Some(*v as u8))
552 } else {
553 Ok(None)
554 }
555}
556
557pub fn decode_white_point_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
559 if let tlv::TlvItemValue::Int(v) = inp {
560 Ok(*v as u16)
561 } else {
562 Err(anyhow::anyhow!("Expected Integer"))
563 }
564}
565
566pub fn decode_white_point_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
568 if let tlv::TlvItemValue::Int(v) = inp {
569 Ok(*v as u16)
570 } else {
571 Err(anyhow::anyhow!("Expected Integer"))
572 }
573}
574
575pub fn decode_color_point_rx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
577 if let tlv::TlvItemValue::Int(v) = inp {
578 Ok(*v as u16)
579 } else {
580 Err(anyhow::anyhow!("Expected Integer"))
581 }
582}
583
584pub fn decode_color_point_ry(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
586 if let tlv::TlvItemValue::Int(v) = inp {
587 Ok(*v as u16)
588 } else {
589 Err(anyhow::anyhow!("Expected Integer"))
590 }
591}
592
593pub fn decode_color_point_r_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
595 if let tlv::TlvItemValue::Int(v) = inp {
596 Ok(Some(*v as u8))
597 } else {
598 Ok(None)
599 }
600}
601
602pub fn decode_color_point_gx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
604 if let tlv::TlvItemValue::Int(v) = inp {
605 Ok(*v as u16)
606 } else {
607 Err(anyhow::anyhow!("Expected Integer"))
608 }
609}
610
611pub fn decode_color_point_gy(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
613 if let tlv::TlvItemValue::Int(v) = inp {
614 Ok(*v as u16)
615 } else {
616 Err(anyhow::anyhow!("Expected Integer"))
617 }
618}
619
620pub fn decode_color_point_g_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
622 if let tlv::TlvItemValue::Int(v) = inp {
623 Ok(Some(*v as u8))
624 } else {
625 Ok(None)
626 }
627}
628
629pub fn decode_color_point_bx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
631 if let tlv::TlvItemValue::Int(v) = inp {
632 Ok(*v as u16)
633 } else {
634 Err(anyhow::anyhow!("Expected Integer"))
635 }
636}
637
638pub fn decode_color_point_by(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
640 if let tlv::TlvItemValue::Int(v) = inp {
641 Ok(*v as u16)
642 } else {
643 Err(anyhow::anyhow!("Expected Integer"))
644 }
645}
646
647pub fn decode_color_point_b_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
649 if let tlv::TlvItemValue::Int(v) = inp {
650 Ok(Some(*v as u8))
651 } else {
652 Ok(None)
653 }
654}
655
656pub fn decode_enhanced_current_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
658 if let tlv::TlvItemValue::Int(v) = inp {
659 Ok(*v as u16)
660 } else {
661 Err(anyhow::anyhow!("Expected Integer"))
662 }
663}
664
665pub fn decode_enhanced_color_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
667 if let tlv::TlvItemValue::Int(v) = inp {
668 Ok(*v as u8)
669 } else {
670 Err(anyhow::anyhow!("Expected Integer"))
671 }
672}
673
674pub fn decode_color_loop_active(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
676 if let tlv::TlvItemValue::Int(v) = inp {
677 Ok(*v as u8)
678 } else {
679 Err(anyhow::anyhow!("Expected Integer"))
680 }
681}
682
683pub fn decode_color_loop_direction(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
685 if let tlv::TlvItemValue::Int(v) = inp {
686 Ok(*v as u8)
687 } else {
688 Err(anyhow::anyhow!("Expected Integer"))
689 }
690}
691
692pub fn decode_color_loop_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
694 if let tlv::TlvItemValue::Int(v) = inp {
695 Ok(*v as u16)
696 } else {
697 Err(anyhow::anyhow!("Expected Integer"))
698 }
699}
700
701pub fn decode_color_loop_start_enhanced_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
703 if let tlv::TlvItemValue::Int(v) = inp {
704 Ok(*v as u16)
705 } else {
706 Err(anyhow::anyhow!("Expected Integer"))
707 }
708}
709
710pub fn decode_color_loop_stored_enhanced_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
712 if let tlv::TlvItemValue::Int(v) = inp {
713 Ok(*v as u16)
714 } else {
715 Err(anyhow::anyhow!("Expected Integer"))
716 }
717}
718
719pub fn decode_color_capabilities(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
721 if let tlv::TlvItemValue::Int(v) = inp {
722 Ok(*v as u8)
723 } else {
724 Err(anyhow::anyhow!("Expected Integer"))
725 }
726}
727
728pub fn decode_color_temp_physical_min_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
730 if let tlv::TlvItemValue::Int(v) = inp {
731 Ok(*v as u16)
732 } else {
733 Err(anyhow::anyhow!("Expected Integer"))
734 }
735}
736
737pub fn decode_color_temp_physical_max_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
739 if let tlv::TlvItemValue::Int(v) = inp {
740 Ok(*v as u16)
741 } else {
742 Err(anyhow::anyhow!("Expected Integer"))
743 }
744}
745
746pub fn decode_couple_color_temp_to_level_min_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
748 if let tlv::TlvItemValue::Int(v) = inp {
749 Ok(*v as u16)
750 } else {
751 Err(anyhow::anyhow!("Expected Integer"))
752 }
753}
754
755pub fn decode_start_up_color_temperature_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
757 if let tlv::TlvItemValue::Int(v) = inp {
758 Ok(Some(*v as u16))
759 } else {
760 Ok(None)
761 }
762}
763
764
765pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
777 if cluster_id != 0x0300 {
779 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0300, got {}\"}}", cluster_id);
780 }
781
782 match attribute_id {
783 0x0000 => {
784 match decode_current_hue(tlv_value) {
785 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
786 Err(e) => format!("{{\"error\": \"{}\"}}", e),
787 }
788 }
789 0x0001 => {
790 match decode_current_saturation(tlv_value) {
791 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
792 Err(e) => format!("{{\"error\": \"{}\"}}", e),
793 }
794 }
795 0x0002 => {
796 match decode_remaining_time(tlv_value) {
797 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
798 Err(e) => format!("{{\"error\": \"{}\"}}", e),
799 }
800 }
801 0x0003 => {
802 match decode_current_x(tlv_value) {
803 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
804 Err(e) => format!("{{\"error\": \"{}\"}}", e),
805 }
806 }
807 0x0004 => {
808 match decode_current_y(tlv_value) {
809 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
810 Err(e) => format!("{{\"error\": \"{}\"}}", e),
811 }
812 }
813 0x0005 => {
814 match decode_drift_compensation(tlv_value) {
815 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
816 Err(e) => format!("{{\"error\": \"{}\"}}", e),
817 }
818 }
819 0x0006 => {
820 match decode_compensation_text(tlv_value) {
821 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
822 Err(e) => format!("{{\"error\": \"{}\"}}", e),
823 }
824 }
825 0x0007 => {
826 match decode_color_temperature_mireds(tlv_value) {
827 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
828 Err(e) => format!("{{\"error\": \"{}\"}}", e),
829 }
830 }
831 0x0008 => {
832 match decode_color_mode(tlv_value) {
833 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
834 Err(e) => format!("{{\"error\": \"{}\"}}", e),
835 }
836 }
837 0x000F => {
838 match decode_options(tlv_value) {
839 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
840 Err(e) => format!("{{\"error\": \"{}\"}}", e),
841 }
842 }
843 0x0010 => {
844 match decode_number_of_primaries(tlv_value) {
845 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
846 Err(e) => format!("{{\"error\": \"{}\"}}", e),
847 }
848 }
849 0x0011 => {
850 match decode_primary1_x(tlv_value) {
851 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
852 Err(e) => format!("{{\"error\": \"{}\"}}", e),
853 }
854 }
855 0x0012 => {
856 match decode_primary1_y(tlv_value) {
857 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
858 Err(e) => format!("{{\"error\": \"{}\"}}", e),
859 }
860 }
861 0x0013 => {
862 match decode_primary1_intensity(tlv_value) {
863 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
864 Err(e) => format!("{{\"error\": \"{}\"}}", e),
865 }
866 }
867 0x0015 => {
868 match decode_primary2_x(tlv_value) {
869 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
870 Err(e) => format!("{{\"error\": \"{}\"}}", e),
871 }
872 }
873 0x0016 => {
874 match decode_primary2_y(tlv_value) {
875 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
876 Err(e) => format!("{{\"error\": \"{}\"}}", e),
877 }
878 }
879 0x0017 => {
880 match decode_primary2_intensity(tlv_value) {
881 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
882 Err(e) => format!("{{\"error\": \"{}\"}}", e),
883 }
884 }
885 0x0019 => {
886 match decode_primary3_x(tlv_value) {
887 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
888 Err(e) => format!("{{\"error\": \"{}\"}}", e),
889 }
890 }
891 0x001A => {
892 match decode_primary3_y(tlv_value) {
893 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
894 Err(e) => format!("{{\"error\": \"{}\"}}", e),
895 }
896 }
897 0x001B => {
898 match decode_primary3_intensity(tlv_value) {
899 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
900 Err(e) => format!("{{\"error\": \"{}\"}}", e),
901 }
902 }
903 0x0020 => {
904 match decode_primary4_x(tlv_value) {
905 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
906 Err(e) => format!("{{\"error\": \"{}\"}}", e),
907 }
908 }
909 0x0021 => {
910 match decode_primary4_y(tlv_value) {
911 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
912 Err(e) => format!("{{\"error\": \"{}\"}}", e),
913 }
914 }
915 0x0022 => {
916 match decode_primary4_intensity(tlv_value) {
917 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
918 Err(e) => format!("{{\"error\": \"{}\"}}", e),
919 }
920 }
921 0x0024 => {
922 match decode_primary5_x(tlv_value) {
923 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
924 Err(e) => format!("{{\"error\": \"{}\"}}", e),
925 }
926 }
927 0x0025 => {
928 match decode_primary5_y(tlv_value) {
929 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
930 Err(e) => format!("{{\"error\": \"{}\"}}", e),
931 }
932 }
933 0x0026 => {
934 match decode_primary5_intensity(tlv_value) {
935 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
936 Err(e) => format!("{{\"error\": \"{}\"}}", e),
937 }
938 }
939 0x0028 => {
940 match decode_primary6_x(tlv_value) {
941 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
942 Err(e) => format!("{{\"error\": \"{}\"}}", e),
943 }
944 }
945 0x0029 => {
946 match decode_primary6_y(tlv_value) {
947 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
948 Err(e) => format!("{{\"error\": \"{}\"}}", e),
949 }
950 }
951 0x002A => {
952 match decode_primary6_intensity(tlv_value) {
953 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
954 Err(e) => format!("{{\"error\": \"{}\"}}", e),
955 }
956 }
957 0x0030 => {
958 match decode_white_point_x(tlv_value) {
959 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
960 Err(e) => format!("{{\"error\": \"{}\"}}", e),
961 }
962 }
963 0x0031 => {
964 match decode_white_point_y(tlv_value) {
965 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
966 Err(e) => format!("{{\"error\": \"{}\"}}", e),
967 }
968 }
969 0x0032 => {
970 match decode_color_point_rx(tlv_value) {
971 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
972 Err(e) => format!("{{\"error\": \"{}\"}}", e),
973 }
974 }
975 0x0033 => {
976 match decode_color_point_ry(tlv_value) {
977 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
978 Err(e) => format!("{{\"error\": \"{}\"}}", e),
979 }
980 }
981 0x0034 => {
982 match decode_color_point_r_intensity(tlv_value) {
983 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
984 Err(e) => format!("{{\"error\": \"{}\"}}", e),
985 }
986 }
987 0x0036 => {
988 match decode_color_point_gx(tlv_value) {
989 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
990 Err(e) => format!("{{\"error\": \"{}\"}}", e),
991 }
992 }
993 0x0037 => {
994 match decode_color_point_gy(tlv_value) {
995 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
996 Err(e) => format!("{{\"error\": \"{}\"}}", e),
997 }
998 }
999 0x0038 => {
1000 match decode_color_point_g_intensity(tlv_value) {
1001 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1002 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1003 }
1004 }
1005 0x003A => {
1006 match decode_color_point_bx(tlv_value) {
1007 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1008 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1009 }
1010 }
1011 0x003B => {
1012 match decode_color_point_by(tlv_value) {
1013 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1014 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1015 }
1016 }
1017 0x003C => {
1018 match decode_color_point_b_intensity(tlv_value) {
1019 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1020 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1021 }
1022 }
1023 0x4000 => {
1024 match decode_enhanced_current_hue(tlv_value) {
1025 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1026 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1027 }
1028 }
1029 0x4001 => {
1030 match decode_enhanced_color_mode(tlv_value) {
1031 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1032 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1033 }
1034 }
1035 0x4002 => {
1036 match decode_color_loop_active(tlv_value) {
1037 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1038 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1039 }
1040 }
1041 0x4003 => {
1042 match decode_color_loop_direction(tlv_value) {
1043 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1044 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1045 }
1046 }
1047 0x4004 => {
1048 match decode_color_loop_time(tlv_value) {
1049 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1050 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1051 }
1052 }
1053 0x4005 => {
1054 match decode_color_loop_start_enhanced_hue(tlv_value) {
1055 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1056 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1057 }
1058 }
1059 0x4006 => {
1060 match decode_color_loop_stored_enhanced_hue(tlv_value) {
1061 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1062 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1063 }
1064 }
1065 0x400A => {
1066 match decode_color_capabilities(tlv_value) {
1067 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1068 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1069 }
1070 }
1071 0x400B => {
1072 match decode_color_temp_physical_min_mireds(tlv_value) {
1073 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1074 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1075 }
1076 }
1077 0x400C => {
1078 match decode_color_temp_physical_max_mireds(tlv_value) {
1079 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1080 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1081 }
1082 }
1083 0x400D => {
1084 match decode_couple_color_temp_to_level_min_mireds(tlv_value) {
1085 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1086 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1087 }
1088 }
1089 0x4010 => {
1090 match decode_start_up_color_temperature_mireds(tlv_value) {
1091 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1092 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1093 }
1094 }
1095 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1096 }
1097}
1098
1099pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1104 vec![
1105 (0x0000, "CurrentHue"),
1106 (0x0001, "CurrentSaturation"),
1107 (0x0002, "RemainingTime"),
1108 (0x0003, "CurrentX"),
1109 (0x0004, "CurrentY"),
1110 (0x0005, "DriftCompensation"),
1111 (0x0006, "CompensationText"),
1112 (0x0007, "ColorTemperatureMireds"),
1113 (0x0008, "ColorMode"),
1114 (0x000F, "Options"),
1115 (0x0010, "NumberOfPrimaries"),
1116 (0x0011, "Primary1X"),
1117 (0x0012, "Primary1Y"),
1118 (0x0013, "Primary1Intensity"),
1119 (0x0015, "Primary2X"),
1120 (0x0016, "Primary2Y"),
1121 (0x0017, "Primary2Intensity"),
1122 (0x0019, "Primary3X"),
1123 (0x001A, "Primary3Y"),
1124 (0x001B, "Primary3Intensity"),
1125 (0x0020, "Primary4X"),
1126 (0x0021, "Primary4Y"),
1127 (0x0022, "Primary4Intensity"),
1128 (0x0024, "Primary5X"),
1129 (0x0025, "Primary5Y"),
1130 (0x0026, "Primary5Intensity"),
1131 (0x0028, "Primary6X"),
1132 (0x0029, "Primary6Y"),
1133 (0x002A, "Primary6Intensity"),
1134 (0x0030, "WhitePointX"),
1135 (0x0031, "WhitePointY"),
1136 (0x0032, "ColorPointRX"),
1137 (0x0033, "ColorPointRY"),
1138 (0x0034, "ColorPointRIntensity"),
1139 (0x0036, "ColorPointGX"),
1140 (0x0037, "ColorPointGY"),
1141 (0x0038, "ColorPointGIntensity"),
1142 (0x003A, "ColorPointBX"),
1143 (0x003B, "ColorPointBY"),
1144 (0x003C, "ColorPointBIntensity"),
1145 (0x4000, "EnhancedCurrentHue"),
1146 (0x4001, "EnhancedColorMode"),
1147 (0x4002, "ColorLoopActive"),
1148 (0x4003, "ColorLoopDirection"),
1149 (0x4004, "ColorLoopTime"),
1150 (0x4005, "ColorLoopStartEnhancedHue"),
1151 (0x4006, "ColorLoopStoredEnhancedHue"),
1152 (0x400A, "ColorCapabilities"),
1153 (0x400B, "ColorTempPhysicalMinMireds"),
1154 (0x400C, "ColorTempPhysicalMaxMireds"),
1155 (0x400D, "CoupleColorTempToLevelMinMireds"),
1156 (0x4010, "StartUpColorTemperatureMireds"),
1157 ]
1158}
1159