1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
14#[repr(u8)]
15pub enum ColorLoopAction {
16 Deactivate = 0,
18 Activatefromcolorloopstartenhancedhue = 1,
20 Activatefromenhancedcurrenthue = 2,
22}
23
24impl ColorLoopAction {
25 pub fn from_u8(value: u8) -> Option<Self> {
27 match value {
28 0 => Some(ColorLoopAction::Deactivate),
29 1 => Some(ColorLoopAction::Activatefromcolorloopstartenhancedhue),
30 2 => Some(ColorLoopAction::Activatefromenhancedcurrenthue),
31 _ => None,
32 }
33 }
34
35 pub fn to_u8(self) -> u8 {
37 self as u8
38 }
39}
40
41impl From<ColorLoopAction> for u8 {
42 fn from(val: ColorLoopAction) -> Self {
43 val as u8
44 }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
48#[repr(u8)]
49pub enum ColorLoopDirection {
50 Decrement = 0,
52 Increment = 1,
54}
55
56impl ColorLoopDirection {
57 pub fn from_u8(value: u8) -> Option<Self> {
59 match value {
60 0 => Some(ColorLoopDirection::Decrement),
61 1 => Some(ColorLoopDirection::Increment),
62 _ => None,
63 }
64 }
65
66 pub fn to_u8(self) -> u8 {
68 self as u8
69 }
70}
71
72impl From<ColorLoopDirection> for u8 {
73 fn from(val: ColorLoopDirection) -> Self {
74 val as u8
75 }
76}
77
78#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
79#[repr(u8)]
80pub enum ColorMode {
81 Currenthueandcurrentsaturation = 0,
83 Currentxandcurrenty = 1,
85 Colortemperaturemireds = 2,
87}
88
89impl ColorMode {
90 pub fn from_u8(value: u8) -> Option<Self> {
92 match value {
93 0 => Some(ColorMode::Currenthueandcurrentsaturation),
94 1 => Some(ColorMode::Currentxandcurrenty),
95 2 => Some(ColorMode::Colortemperaturemireds),
96 _ => None,
97 }
98 }
99
100 pub fn to_u8(self) -> u8 {
102 self as u8
103 }
104}
105
106impl From<ColorMode> for u8 {
107 fn from(val: ColorMode) -> Self {
108 val as u8
109 }
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
113#[repr(u8)]
114pub enum Direction {
115 Shortest = 0,
117 Longest = 1,
119 Up = 2,
121 Down = 3,
123}
124
125impl Direction {
126 pub fn from_u8(value: u8) -> Option<Self> {
128 match value {
129 0 => Some(Direction::Shortest),
130 1 => Some(Direction::Longest),
131 2 => Some(Direction::Up),
132 3 => Some(Direction::Down),
133 _ => None,
134 }
135 }
136
137 pub fn to_u8(self) -> u8 {
139 self as u8
140 }
141}
142
143impl From<Direction> for u8 {
144 fn from(val: Direction) -> Self {
145 val as u8
146 }
147}
148
149#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
150#[repr(u8)]
151pub enum DriftCompensation {
152 None = 0,
154 Otherorunknown = 1,
156 Temperaturemonitoring = 2,
158 Opticalluminancemonitoringandfeedback = 3,
160 Opticalcolormonitoringandfeedback = 4,
162}
163
164impl DriftCompensation {
165 pub fn from_u8(value: u8) -> Option<Self> {
167 match value {
168 0 => Some(DriftCompensation::None),
169 1 => Some(DriftCompensation::Otherorunknown),
170 2 => Some(DriftCompensation::Temperaturemonitoring),
171 3 => Some(DriftCompensation::Opticalluminancemonitoringandfeedback),
172 4 => Some(DriftCompensation::Opticalcolormonitoringandfeedback),
173 _ => None,
174 }
175 }
176
177 pub fn to_u8(self) -> u8 {
179 self as u8
180 }
181}
182
183impl From<DriftCompensation> for u8 {
184 fn from(val: DriftCompensation) -> Self {
185 val as u8
186 }
187}
188
189#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
190#[repr(u8)]
191pub enum EnhancedColorMode {
192 Currenthueandcurrentsaturation = 0,
194 Currentxandcurrenty = 1,
196 Colortemperaturemireds = 2,
198 Enhancedcurrenthueandcurrentsaturation = 3,
200}
201
202impl EnhancedColorMode {
203 pub fn from_u8(value: u8) -> Option<Self> {
205 match value {
206 0 => Some(EnhancedColorMode::Currenthueandcurrentsaturation),
207 1 => Some(EnhancedColorMode::Currentxandcurrenty),
208 2 => Some(EnhancedColorMode::Colortemperaturemireds),
209 3 => Some(EnhancedColorMode::Enhancedcurrenthueandcurrentsaturation),
210 _ => None,
211 }
212 }
213
214 pub fn to_u8(self) -> u8 {
216 self as u8
217 }
218}
219
220impl From<EnhancedColorMode> for u8 {
221 fn from(val: EnhancedColorMode) -> Self {
222 val as u8
223 }
224}
225
226#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
227#[repr(u8)]
228pub enum MoveMode {
229 Stop = 0,
231 Up = 1,
233 Down = 3,
235}
236
237impl MoveMode {
238 pub fn from_u8(value: u8) -> Option<Self> {
240 match value {
241 0 => Some(MoveMode::Stop),
242 1 => Some(MoveMode::Up),
243 3 => Some(MoveMode::Down),
244 _ => None,
245 }
246 }
247
248 pub fn to_u8(self) -> u8 {
250 self as u8
251 }
252}
253
254impl From<MoveMode> for u8 {
255 fn from(val: MoveMode) -> Self {
256 val as u8
257 }
258}
259
260#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
261#[repr(u8)]
262pub enum StepMode {
263 Up = 1,
265 Down = 3,
267}
268
269impl StepMode {
270 pub fn from_u8(value: u8) -> Option<Self> {
272 match value {
273 1 => Some(StepMode::Up),
274 3 => Some(StepMode::Down),
275 _ => None,
276 }
277 }
278
279 pub fn to_u8(self) -> u8 {
281 self as u8
282 }
283}
284
285impl From<StepMode> for u8 {
286 fn from(val: StepMode) -> Self {
287 val as u8
288 }
289}
290
291pub type ColorCapabilities = u8;
295
296pub mod colorcapabilities {
298 pub const HUE_SATURATION: u8 = 0x01;
300 pub const ENHANCED_HUE: u8 = 0x02;
302 pub const COLOR_LOOP: u8 = 0x04;
304 pub const XY: u8 = 0x08;
306 pub const COLOR_TEMPERATURE: u8 = 0x10;
308}
309
310pub type Options = u8;
312
313pub mod options {
315 pub const EXECUTE_IF_OFF: u8 = 0x01;
317}
318
319pub type UpdateFlags = u8;
321
322pub mod updateflags {
324 pub const UPDATE_ACTION: u8 = 0x01;
326 pub const UPDATE_DIRECTION: u8 = 0x02;
328 pub const UPDATE_TIME: u8 = 0x04;
330 pub const UPDATE_START_HUE: u8 = 0x08;
332}
333
334pub fn encode_move_to_hue(hue: u8, direction: Direction, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
338 let tlv = tlv::TlvItemEnc {
339 tag: 0,
340 value: tlv::TlvItemValueEnc::StructInvisible(vec![
341 (0, tlv::TlvItemValueEnc::UInt8(hue)).into(),
342 (1, tlv::TlvItemValueEnc::UInt8(direction.to_u8())).into(),
343 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
344 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
345 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
346 ]),
347 };
348 Ok(tlv.encode()?)
349}
350
351pub fn encode_move_hue(move_mode: MoveMode, rate: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
353 let tlv = tlv::TlvItemEnc {
354 tag: 0,
355 value: tlv::TlvItemValueEnc::StructInvisible(vec![
356 (0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
357 (1, tlv::TlvItemValueEnc::UInt8(rate)).into(),
358 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
359 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
360 ]),
361 };
362 Ok(tlv.encode()?)
363}
364
365pub fn encode_step_hue(step_mode: StepMode, step_size: u8, transition_time: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
367 let tlv = tlv::TlvItemEnc {
368 tag: 0,
369 value: tlv::TlvItemValueEnc::StructInvisible(vec![
370 (0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
371 (1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
372 (2, tlv::TlvItemValueEnc::UInt8(transition_time)).into(),
373 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
374 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
375 ]),
376 };
377 Ok(tlv.encode()?)
378}
379
380pub fn encode_move_to_saturation(saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
382 let tlv = tlv::TlvItemEnc {
383 tag: 0,
384 value: tlv::TlvItemValueEnc::StructInvisible(vec![
385 (0, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
386 (1, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
387 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
388 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
389 ]),
390 };
391 Ok(tlv.encode()?)
392}
393
394pub fn encode_move_saturation(move_mode: MoveMode, rate: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
396 let tlv = tlv::TlvItemEnc {
397 tag: 0,
398 value: tlv::TlvItemValueEnc::StructInvisible(vec![
399 (0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
400 (1, tlv::TlvItemValueEnc::UInt8(rate)).into(),
401 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
402 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
403 ]),
404 };
405 Ok(tlv.encode()?)
406}
407
408pub fn encode_step_saturation(step_mode: StepMode, step_size: u8, transition_time: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
410 let tlv = tlv::TlvItemEnc {
411 tag: 0,
412 value: tlv::TlvItemValueEnc::StructInvisible(vec![
413 (0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
414 (1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
415 (2, tlv::TlvItemValueEnc::UInt8(transition_time)).into(),
416 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
417 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
418 ]),
419 };
420 Ok(tlv.encode()?)
421}
422
423pub fn encode_move_to_hue_and_saturation(hue: u8, saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
425 let tlv = tlv::TlvItemEnc {
426 tag: 0,
427 value: tlv::TlvItemValueEnc::StructInvisible(vec![
428 (0, tlv::TlvItemValueEnc::UInt8(hue)).into(),
429 (1, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
430 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
431 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
432 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
433 ]),
434 };
435 Ok(tlv.encode()?)
436}
437
438pub fn encode_move_to_color(color_x: u16, color_y: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
440 let tlv = tlv::TlvItemEnc {
441 tag: 0,
442 value: tlv::TlvItemValueEnc::StructInvisible(vec![
443 (0, tlv::TlvItemValueEnc::UInt16(color_x)).into(),
444 (1, tlv::TlvItemValueEnc::UInt16(color_y)).into(),
445 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
446 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
447 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
448 ]),
449 };
450 Ok(tlv.encode()?)
451}
452
453pub fn encode_move_color(rate_x: i16, rate_y: i16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
455 let tlv = tlv::TlvItemEnc {
456 tag: 0,
457 value: tlv::TlvItemValueEnc::StructInvisible(vec![
458 (0, tlv::TlvItemValueEnc::Int16(rate_x)).into(),
459 (1, tlv::TlvItemValueEnc::Int16(rate_y)).into(),
460 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
461 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
462 ]),
463 };
464 Ok(tlv.encode()?)
465}
466
467pub fn encode_step_color(step_x: i16, step_y: i16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
469 let tlv = tlv::TlvItemEnc {
470 tag: 0,
471 value: tlv::TlvItemValueEnc::StructInvisible(vec![
472 (0, tlv::TlvItemValueEnc::Int16(step_x)).into(),
473 (1, tlv::TlvItemValueEnc::Int16(step_y)).into(),
474 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
475 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
476 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
477 ]),
478 };
479 Ok(tlv.encode()?)
480}
481
482pub fn encode_move_to_color_temperature(color_temperature_mireds: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
484 let tlv = tlv::TlvItemEnc {
485 tag: 0,
486 value: tlv::TlvItemValueEnc::StructInvisible(vec![
487 (0, tlv::TlvItemValueEnc::UInt16(color_temperature_mireds)).into(),
488 (1, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
489 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
490 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
491 ]),
492 };
493 Ok(tlv.encode()?)
494}
495
496pub fn encode_enhanced_move_to_hue(enhanced_hue: u16, direction: Direction, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
498 let tlv = tlv::TlvItemEnc {
499 tag: 0,
500 value: tlv::TlvItemValueEnc::StructInvisible(vec![
501 (0, tlv::TlvItemValueEnc::UInt16(enhanced_hue)).into(),
502 (1, tlv::TlvItemValueEnc::UInt8(direction.to_u8())).into(),
503 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
504 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
505 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
506 ]),
507 };
508 Ok(tlv.encode()?)
509}
510
511pub fn encode_enhanced_move_hue(move_mode: MoveMode, rate: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
513 let tlv = tlv::TlvItemEnc {
514 tag: 0,
515 value: tlv::TlvItemValueEnc::StructInvisible(vec![
516 (0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
517 (1, tlv::TlvItemValueEnc::UInt16(rate)).into(),
518 (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
519 (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
520 ]),
521 };
522 Ok(tlv.encode()?)
523}
524
525pub fn encode_enhanced_step_hue(step_mode: StepMode, step_size: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
527 let tlv = tlv::TlvItemEnc {
528 tag: 0,
529 value: tlv::TlvItemValueEnc::StructInvisible(vec![
530 (0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
531 (1, tlv::TlvItemValueEnc::UInt16(step_size)).into(),
532 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
533 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
534 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
535 ]),
536 };
537 Ok(tlv.encode()?)
538}
539
540pub fn encode_enhanced_move_to_hue_and_saturation(enhanced_hue: u16, saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
542 let tlv = tlv::TlvItemEnc {
543 tag: 0,
544 value: tlv::TlvItemValueEnc::StructInvisible(vec![
545 (0, tlv::TlvItemValueEnc::UInt16(enhanced_hue)).into(),
546 (1, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
547 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
548 (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
549 (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
550 ]),
551 };
552 Ok(tlv.encode()?)
553}
554
555pub fn encode_color_loop_set(update_flags: UpdateFlags, action: ColorLoopAction, direction: ColorLoopDirection, time: u16, start_hue: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
557 let tlv = tlv::TlvItemEnc {
558 tag: 0,
559 value: tlv::TlvItemValueEnc::StructInvisible(vec![
560 (0, tlv::TlvItemValueEnc::UInt8(update_flags)).into(),
561 (1, tlv::TlvItemValueEnc::UInt8(action.to_u8())).into(),
562 (2, tlv::TlvItemValueEnc::UInt8(direction.to_u8())).into(),
563 (3, tlv::TlvItemValueEnc::UInt16(time)).into(),
564 (4, tlv::TlvItemValueEnc::UInt16(start_hue)).into(),
565 (5, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
566 (6, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
567 ]),
568 };
569 Ok(tlv.encode()?)
570}
571
572pub fn encode_stop_move_step(options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
574 let tlv = tlv::TlvItemEnc {
575 tag: 0,
576 value: tlv::TlvItemValueEnc::StructInvisible(vec![
577 (0, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
578 (1, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
579 ]),
580 };
581 Ok(tlv.encode()?)
582}
583
584pub fn encode_move_color_temperature(move_mode: MoveMode, rate: u16, color_temperature_minimum_mireds: u16, color_temperature_maximum_mireds: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
586 let tlv = tlv::TlvItemEnc {
587 tag: 0,
588 value: tlv::TlvItemValueEnc::StructInvisible(vec![
589 (0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
590 (1, tlv::TlvItemValueEnc::UInt16(rate)).into(),
591 (2, tlv::TlvItemValueEnc::UInt16(color_temperature_minimum_mireds)).into(),
592 (3, tlv::TlvItemValueEnc::UInt16(color_temperature_maximum_mireds)).into(),
593 (4, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
594 (5, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
595 ]),
596 };
597 Ok(tlv.encode()?)
598}
599
600pub fn encode_step_color_temperature(step_mode: StepMode, step_size: u16, transition_time: u16, color_temperature_minimum_mireds: u16, color_temperature_maximum_mireds: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
602 let tlv = tlv::TlvItemEnc {
603 tag: 0,
604 value: tlv::TlvItemValueEnc::StructInvisible(vec![
605 (0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
606 (1, tlv::TlvItemValueEnc::UInt16(step_size)).into(),
607 (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
608 (3, tlv::TlvItemValueEnc::UInt16(color_temperature_minimum_mireds)).into(),
609 (4, tlv::TlvItemValueEnc::UInt16(color_temperature_maximum_mireds)).into(),
610 (5, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
611 (6, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
612 ]),
613 };
614 Ok(tlv.encode()?)
615}
616
617pub fn decode_current_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
621 if let tlv::TlvItemValue::Int(v) = inp {
622 Ok(*v as u8)
623 } else {
624 Err(anyhow::anyhow!("Expected UInt8"))
625 }
626}
627
628pub fn decode_current_saturation(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
630 if let tlv::TlvItemValue::Int(v) = inp {
631 Ok(*v as u8)
632 } else {
633 Err(anyhow::anyhow!("Expected UInt8"))
634 }
635}
636
637pub fn decode_remaining_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
639 if let tlv::TlvItemValue::Int(v) = inp {
640 Ok(*v as u16)
641 } else {
642 Err(anyhow::anyhow!("Expected UInt16"))
643 }
644}
645
646pub fn decode_current_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
648 if let tlv::TlvItemValue::Int(v) = inp {
649 Ok(*v as u16)
650 } else {
651 Err(anyhow::anyhow!("Expected UInt16"))
652 }
653}
654
655pub fn decode_current_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
657 if let tlv::TlvItemValue::Int(v) = inp {
658 Ok(*v as u16)
659 } else {
660 Err(anyhow::anyhow!("Expected UInt16"))
661 }
662}
663
664pub fn decode_drift_compensation(inp: &tlv::TlvItemValue) -> anyhow::Result<DriftCompensation> {
666 if let tlv::TlvItemValue::Int(v) = inp {
667 DriftCompensation::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
668 } else {
669 Err(anyhow::anyhow!("Expected Integer"))
670 }
671}
672
673pub fn decode_compensation_text(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
675 if let tlv::TlvItemValue::String(v) = inp {
676 Ok(v.clone())
677 } else {
678 Err(anyhow::anyhow!("Expected String"))
679 }
680}
681
682pub fn decode_color_temperature_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
684 if let tlv::TlvItemValue::Int(v) = inp {
685 Ok(*v as u16)
686 } else {
687 Err(anyhow::anyhow!("Expected UInt16"))
688 }
689}
690
691pub fn decode_color_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<ColorMode> {
693 if let tlv::TlvItemValue::Int(v) = inp {
694 ColorMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
695 } else {
696 Err(anyhow::anyhow!("Expected Integer"))
697 }
698}
699
700pub fn decode_options(inp: &tlv::TlvItemValue) -> anyhow::Result<Options> {
702 if let tlv::TlvItemValue::Int(v) = inp {
703 Ok(*v as u8)
704 } else {
705 Err(anyhow::anyhow!("Expected Integer"))
706 }
707}
708
709pub fn decode_number_of_primaries(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
711 if let tlv::TlvItemValue::Int(v) = inp {
712 Ok(Some(*v as u8))
713 } else {
714 Ok(None)
715 }
716}
717
718pub fn decode_primary1_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
720 if let tlv::TlvItemValue::Int(v) = inp {
721 Ok(*v as u16)
722 } else {
723 Err(anyhow::anyhow!("Expected UInt16"))
724 }
725}
726
727pub fn decode_primary1_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
729 if let tlv::TlvItemValue::Int(v) = inp {
730 Ok(*v as u16)
731 } else {
732 Err(anyhow::anyhow!("Expected UInt16"))
733 }
734}
735
736pub fn decode_primary1_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
738 if let tlv::TlvItemValue::Int(v) = inp {
739 Ok(Some(*v as u8))
740 } else {
741 Ok(None)
742 }
743}
744
745pub fn decode_primary2_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
747 if let tlv::TlvItemValue::Int(v) = inp {
748 Ok(*v as u16)
749 } else {
750 Err(anyhow::anyhow!("Expected UInt16"))
751 }
752}
753
754pub fn decode_primary2_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
756 if let tlv::TlvItemValue::Int(v) = inp {
757 Ok(*v as u16)
758 } else {
759 Err(anyhow::anyhow!("Expected UInt16"))
760 }
761}
762
763pub fn decode_primary2_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
765 if let tlv::TlvItemValue::Int(v) = inp {
766 Ok(Some(*v as u8))
767 } else {
768 Ok(None)
769 }
770}
771
772pub fn decode_primary3_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
774 if let tlv::TlvItemValue::Int(v) = inp {
775 Ok(*v as u16)
776 } else {
777 Err(anyhow::anyhow!("Expected UInt16"))
778 }
779}
780
781pub fn decode_primary3_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
783 if let tlv::TlvItemValue::Int(v) = inp {
784 Ok(*v as u16)
785 } else {
786 Err(anyhow::anyhow!("Expected UInt16"))
787 }
788}
789
790pub fn decode_primary3_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
792 if let tlv::TlvItemValue::Int(v) = inp {
793 Ok(Some(*v as u8))
794 } else {
795 Ok(None)
796 }
797}
798
799pub fn decode_primary4_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
801 if let tlv::TlvItemValue::Int(v) = inp {
802 Ok(*v as u16)
803 } else {
804 Err(anyhow::anyhow!("Expected UInt16"))
805 }
806}
807
808pub fn decode_primary4_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
810 if let tlv::TlvItemValue::Int(v) = inp {
811 Ok(*v as u16)
812 } else {
813 Err(anyhow::anyhow!("Expected UInt16"))
814 }
815}
816
817pub fn decode_primary4_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
819 if let tlv::TlvItemValue::Int(v) = inp {
820 Ok(Some(*v as u8))
821 } else {
822 Ok(None)
823 }
824}
825
826pub fn decode_primary5_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
828 if let tlv::TlvItemValue::Int(v) = inp {
829 Ok(*v as u16)
830 } else {
831 Err(anyhow::anyhow!("Expected UInt16"))
832 }
833}
834
835pub fn decode_primary5_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
837 if let tlv::TlvItemValue::Int(v) = inp {
838 Ok(*v as u16)
839 } else {
840 Err(anyhow::anyhow!("Expected UInt16"))
841 }
842}
843
844pub fn decode_primary5_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
846 if let tlv::TlvItemValue::Int(v) = inp {
847 Ok(Some(*v as u8))
848 } else {
849 Ok(None)
850 }
851}
852
853pub fn decode_primary6_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
855 if let tlv::TlvItemValue::Int(v) = inp {
856 Ok(*v as u16)
857 } else {
858 Err(anyhow::anyhow!("Expected UInt16"))
859 }
860}
861
862pub fn decode_primary6_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
864 if let tlv::TlvItemValue::Int(v) = inp {
865 Ok(*v as u16)
866 } else {
867 Err(anyhow::anyhow!("Expected UInt16"))
868 }
869}
870
871pub fn decode_primary6_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
873 if let tlv::TlvItemValue::Int(v) = inp {
874 Ok(Some(*v as u8))
875 } else {
876 Ok(None)
877 }
878}
879
880pub fn decode_white_point_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
882 if let tlv::TlvItemValue::Int(v) = inp {
883 Ok(*v as u16)
884 } else {
885 Err(anyhow::anyhow!("Expected UInt16"))
886 }
887}
888
889pub fn decode_white_point_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
891 if let tlv::TlvItemValue::Int(v) = inp {
892 Ok(*v as u16)
893 } else {
894 Err(anyhow::anyhow!("Expected UInt16"))
895 }
896}
897
898pub fn decode_color_point_rx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
900 if let tlv::TlvItemValue::Int(v) = inp {
901 Ok(*v as u16)
902 } else {
903 Err(anyhow::anyhow!("Expected UInt16"))
904 }
905}
906
907pub fn decode_color_point_ry(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
909 if let tlv::TlvItemValue::Int(v) = inp {
910 Ok(*v as u16)
911 } else {
912 Err(anyhow::anyhow!("Expected UInt16"))
913 }
914}
915
916pub fn decode_color_point_r_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
918 if let tlv::TlvItemValue::Int(v) = inp {
919 Ok(Some(*v as u8))
920 } else {
921 Ok(None)
922 }
923}
924
925pub fn decode_color_point_gx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
927 if let tlv::TlvItemValue::Int(v) = inp {
928 Ok(*v as u16)
929 } else {
930 Err(anyhow::anyhow!("Expected UInt16"))
931 }
932}
933
934pub fn decode_color_point_gy(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
936 if let tlv::TlvItemValue::Int(v) = inp {
937 Ok(*v as u16)
938 } else {
939 Err(anyhow::anyhow!("Expected UInt16"))
940 }
941}
942
943pub fn decode_color_point_g_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
945 if let tlv::TlvItemValue::Int(v) = inp {
946 Ok(Some(*v as u8))
947 } else {
948 Ok(None)
949 }
950}
951
952pub fn decode_color_point_bx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
954 if let tlv::TlvItemValue::Int(v) = inp {
955 Ok(*v as u16)
956 } else {
957 Err(anyhow::anyhow!("Expected UInt16"))
958 }
959}
960
961pub fn decode_color_point_by(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
963 if let tlv::TlvItemValue::Int(v) = inp {
964 Ok(*v as u16)
965 } else {
966 Err(anyhow::anyhow!("Expected UInt16"))
967 }
968}
969
970pub fn decode_color_point_b_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
972 if let tlv::TlvItemValue::Int(v) = inp {
973 Ok(Some(*v as u8))
974 } else {
975 Ok(None)
976 }
977}
978
979pub fn decode_enhanced_current_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
981 if let tlv::TlvItemValue::Int(v) = inp {
982 Ok(*v as u16)
983 } else {
984 Err(anyhow::anyhow!("Expected UInt16"))
985 }
986}
987
988pub fn decode_enhanced_color_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<EnhancedColorMode> {
990 if let tlv::TlvItemValue::Int(v) = inp {
991 EnhancedColorMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
992 } else {
993 Err(anyhow::anyhow!("Expected Integer"))
994 }
995}
996
997pub fn decode_color_loop_active(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
999 if let tlv::TlvItemValue::Int(v) = inp {
1000 Ok(*v as u8)
1001 } else {
1002 Err(anyhow::anyhow!("Expected UInt8"))
1003 }
1004}
1005
1006pub fn decode_color_loop_direction(inp: &tlv::TlvItemValue) -> anyhow::Result<ColorLoopDirection> {
1008 if let tlv::TlvItemValue::Int(v) = inp {
1009 ColorLoopDirection::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1010 } else {
1011 Err(anyhow::anyhow!("Expected Integer"))
1012 }
1013}
1014
1015pub fn decode_color_loop_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1017 if let tlv::TlvItemValue::Int(v) = inp {
1018 Ok(*v as u16)
1019 } else {
1020 Err(anyhow::anyhow!("Expected UInt16"))
1021 }
1022}
1023
1024pub fn decode_color_loop_start_enhanced_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1026 if let tlv::TlvItemValue::Int(v) = inp {
1027 Ok(*v as u16)
1028 } else {
1029 Err(anyhow::anyhow!("Expected UInt16"))
1030 }
1031}
1032
1033pub fn decode_color_loop_stored_enhanced_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1035 if let tlv::TlvItemValue::Int(v) = inp {
1036 Ok(*v as u16)
1037 } else {
1038 Err(anyhow::anyhow!("Expected UInt16"))
1039 }
1040}
1041
1042pub fn decode_color_capabilities(inp: &tlv::TlvItemValue) -> anyhow::Result<ColorCapabilities> {
1044 if let tlv::TlvItemValue::Int(v) = inp {
1045 Ok(*v as u8)
1046 } else {
1047 Err(anyhow::anyhow!("Expected Integer"))
1048 }
1049}
1050
1051pub fn decode_color_temp_physical_min_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1053 if let tlv::TlvItemValue::Int(v) = inp {
1054 Ok(*v as u16)
1055 } else {
1056 Err(anyhow::anyhow!("Expected UInt16"))
1057 }
1058}
1059
1060pub fn decode_color_temp_physical_max_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1062 if let tlv::TlvItemValue::Int(v) = inp {
1063 Ok(*v as u16)
1064 } else {
1065 Err(anyhow::anyhow!("Expected UInt16"))
1066 }
1067}
1068
1069pub fn decode_couple_color_temp_to_level_min_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1071 if let tlv::TlvItemValue::Int(v) = inp {
1072 Ok(*v as u16)
1073 } else {
1074 Err(anyhow::anyhow!("Expected UInt16"))
1075 }
1076}
1077
1078pub fn decode_start_up_color_temperature_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
1080 if let tlv::TlvItemValue::Int(v) = inp {
1081 Ok(Some(*v as u16))
1082 } else {
1083 Ok(None)
1084 }
1085}
1086
1087
1088pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
1100 if cluster_id != 0x0300 {
1102 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0300, got {}\"}}", cluster_id);
1103 }
1104
1105 match attribute_id {
1106 0x0000 => {
1107 match decode_current_hue(tlv_value) {
1108 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1109 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1110 }
1111 }
1112 0x0001 => {
1113 match decode_current_saturation(tlv_value) {
1114 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1115 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1116 }
1117 }
1118 0x0002 => {
1119 match decode_remaining_time(tlv_value) {
1120 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1121 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1122 }
1123 }
1124 0x0003 => {
1125 match decode_current_x(tlv_value) {
1126 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1127 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1128 }
1129 }
1130 0x0004 => {
1131 match decode_current_y(tlv_value) {
1132 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1133 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1134 }
1135 }
1136 0x0005 => {
1137 match decode_drift_compensation(tlv_value) {
1138 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1139 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1140 }
1141 }
1142 0x0006 => {
1143 match decode_compensation_text(tlv_value) {
1144 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1145 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1146 }
1147 }
1148 0x0007 => {
1149 match decode_color_temperature_mireds(tlv_value) {
1150 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1151 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1152 }
1153 }
1154 0x0008 => {
1155 match decode_color_mode(tlv_value) {
1156 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1157 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1158 }
1159 }
1160 0x000F => {
1161 match decode_options(tlv_value) {
1162 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1163 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1164 }
1165 }
1166 0x0010 => {
1167 match decode_number_of_primaries(tlv_value) {
1168 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1169 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1170 }
1171 }
1172 0x0011 => {
1173 match decode_primary1_x(tlv_value) {
1174 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1175 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1176 }
1177 }
1178 0x0012 => {
1179 match decode_primary1_y(tlv_value) {
1180 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1181 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1182 }
1183 }
1184 0x0013 => {
1185 match decode_primary1_intensity(tlv_value) {
1186 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1187 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1188 }
1189 }
1190 0x0015 => {
1191 match decode_primary2_x(tlv_value) {
1192 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1193 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1194 }
1195 }
1196 0x0016 => {
1197 match decode_primary2_y(tlv_value) {
1198 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1199 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1200 }
1201 }
1202 0x0017 => {
1203 match decode_primary2_intensity(tlv_value) {
1204 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1205 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1206 }
1207 }
1208 0x0019 => {
1209 match decode_primary3_x(tlv_value) {
1210 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1211 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1212 }
1213 }
1214 0x001A => {
1215 match decode_primary3_y(tlv_value) {
1216 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1217 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1218 }
1219 }
1220 0x001B => {
1221 match decode_primary3_intensity(tlv_value) {
1222 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1223 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1224 }
1225 }
1226 0x0020 => {
1227 match decode_primary4_x(tlv_value) {
1228 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1229 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1230 }
1231 }
1232 0x0021 => {
1233 match decode_primary4_y(tlv_value) {
1234 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1235 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1236 }
1237 }
1238 0x0022 => {
1239 match decode_primary4_intensity(tlv_value) {
1240 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1241 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1242 }
1243 }
1244 0x0024 => {
1245 match decode_primary5_x(tlv_value) {
1246 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1247 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1248 }
1249 }
1250 0x0025 => {
1251 match decode_primary5_y(tlv_value) {
1252 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1253 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1254 }
1255 }
1256 0x0026 => {
1257 match decode_primary5_intensity(tlv_value) {
1258 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1259 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1260 }
1261 }
1262 0x0028 => {
1263 match decode_primary6_x(tlv_value) {
1264 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1265 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1266 }
1267 }
1268 0x0029 => {
1269 match decode_primary6_y(tlv_value) {
1270 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1271 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1272 }
1273 }
1274 0x002A => {
1275 match decode_primary6_intensity(tlv_value) {
1276 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1277 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1278 }
1279 }
1280 0x0030 => {
1281 match decode_white_point_x(tlv_value) {
1282 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1283 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1284 }
1285 }
1286 0x0031 => {
1287 match decode_white_point_y(tlv_value) {
1288 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1289 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1290 }
1291 }
1292 0x0032 => {
1293 match decode_color_point_rx(tlv_value) {
1294 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1295 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1296 }
1297 }
1298 0x0033 => {
1299 match decode_color_point_ry(tlv_value) {
1300 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1301 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1302 }
1303 }
1304 0x0034 => {
1305 match decode_color_point_r_intensity(tlv_value) {
1306 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1307 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1308 }
1309 }
1310 0x0036 => {
1311 match decode_color_point_gx(tlv_value) {
1312 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1313 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1314 }
1315 }
1316 0x0037 => {
1317 match decode_color_point_gy(tlv_value) {
1318 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1319 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1320 }
1321 }
1322 0x0038 => {
1323 match decode_color_point_g_intensity(tlv_value) {
1324 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1325 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1326 }
1327 }
1328 0x003A => {
1329 match decode_color_point_bx(tlv_value) {
1330 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1331 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1332 }
1333 }
1334 0x003B => {
1335 match decode_color_point_by(tlv_value) {
1336 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1337 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1338 }
1339 }
1340 0x003C => {
1341 match decode_color_point_b_intensity(tlv_value) {
1342 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1343 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1344 }
1345 }
1346 0x4000 => {
1347 match decode_enhanced_current_hue(tlv_value) {
1348 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1349 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1350 }
1351 }
1352 0x4001 => {
1353 match decode_enhanced_color_mode(tlv_value) {
1354 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1355 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1356 }
1357 }
1358 0x4002 => {
1359 match decode_color_loop_active(tlv_value) {
1360 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1361 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1362 }
1363 }
1364 0x4003 => {
1365 match decode_color_loop_direction(tlv_value) {
1366 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1367 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1368 }
1369 }
1370 0x4004 => {
1371 match decode_color_loop_time(tlv_value) {
1372 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1373 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1374 }
1375 }
1376 0x4005 => {
1377 match decode_color_loop_start_enhanced_hue(tlv_value) {
1378 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1379 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1380 }
1381 }
1382 0x4006 => {
1383 match decode_color_loop_stored_enhanced_hue(tlv_value) {
1384 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1385 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1386 }
1387 }
1388 0x400A => {
1389 match decode_color_capabilities(tlv_value) {
1390 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1391 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1392 }
1393 }
1394 0x400B => {
1395 match decode_color_temp_physical_min_mireds(tlv_value) {
1396 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1397 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1398 }
1399 }
1400 0x400C => {
1401 match decode_color_temp_physical_max_mireds(tlv_value) {
1402 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1403 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1404 }
1405 }
1406 0x400D => {
1407 match decode_couple_color_temp_to_level_min_mireds(tlv_value) {
1408 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1409 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1410 }
1411 }
1412 0x4010 => {
1413 match decode_start_up_color_temperature_mireds(tlv_value) {
1414 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1415 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1416 }
1417 }
1418 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1419 }
1420}
1421
1422pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1427 vec![
1428 (0x0000, "CurrentHue"),
1429 (0x0001, "CurrentSaturation"),
1430 (0x0002, "RemainingTime"),
1431 (0x0003, "CurrentX"),
1432 (0x0004, "CurrentY"),
1433 (0x0005, "DriftCompensation"),
1434 (0x0006, "CompensationText"),
1435 (0x0007, "ColorTemperatureMireds"),
1436 (0x0008, "ColorMode"),
1437 (0x000F, "Options"),
1438 (0x0010, "NumberOfPrimaries"),
1439 (0x0011, "Primary1X"),
1440 (0x0012, "Primary1Y"),
1441 (0x0013, "Primary1Intensity"),
1442 (0x0015, "Primary2X"),
1443 (0x0016, "Primary2Y"),
1444 (0x0017, "Primary2Intensity"),
1445 (0x0019, "Primary3X"),
1446 (0x001A, "Primary3Y"),
1447 (0x001B, "Primary3Intensity"),
1448 (0x0020, "Primary4X"),
1449 (0x0021, "Primary4Y"),
1450 (0x0022, "Primary4Intensity"),
1451 (0x0024, "Primary5X"),
1452 (0x0025, "Primary5Y"),
1453 (0x0026, "Primary5Intensity"),
1454 (0x0028, "Primary6X"),
1455 (0x0029, "Primary6Y"),
1456 (0x002A, "Primary6Intensity"),
1457 (0x0030, "WhitePointX"),
1458 (0x0031, "WhitePointY"),
1459 (0x0032, "ColorPointRX"),
1460 (0x0033, "ColorPointRY"),
1461 (0x0034, "ColorPointRIntensity"),
1462 (0x0036, "ColorPointGX"),
1463 (0x0037, "ColorPointGY"),
1464 (0x0038, "ColorPointGIntensity"),
1465 (0x003A, "ColorPointBX"),
1466 (0x003B, "ColorPointBY"),
1467 (0x003C, "ColorPointBIntensity"),
1468 (0x4000, "EnhancedCurrentHue"),
1469 (0x4001, "EnhancedColorMode"),
1470 (0x4002, "ColorLoopActive"),
1471 (0x4003, "ColorLoopDirection"),
1472 (0x4004, "ColorLoopTime"),
1473 (0x4005, "ColorLoopStartEnhancedHue"),
1474 (0x4006, "ColorLoopStoredEnhancedHue"),
1475 (0x400A, "ColorCapabilities"),
1476 (0x400B, "ColorTempPhysicalMinMireds"),
1477 (0x400C, "ColorTempPhysicalMaxMireds"),
1478 (0x400D, "CoupleColorTempToLevelMinMireds"),
1479 (0x4010, "StartUpColorTemperatureMireds"),
1480 ]
1481}
1482