matc/clusters/codec/
color_control.rs

1//! Matter TLV encoders and decoders for Color Control Cluster
2//! Cluster ID: 0x0300
3//!
4//! This file is automatically generated from ColorControl.xml
5
6#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13// Enum definitions
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
16#[repr(u8)]
17pub enum ColorLoopAction {
18    /// De-activate the color loop.
19    Deactivate = 0,
20    /// Activate the color loop from the value in the ColorLoopStartEnhancedHue field.
21    Activatefromcolorloopstartenhancedhue = 1,
22    /// Activate the color loop from the value of the EnhancedCurrentHue attribute.
23    Activatefromenhancedcurrenthue = 2,
24}
25
26impl ColorLoopAction {
27    /// Convert from u8 value
28    pub fn from_u8(value: u8) -> Option<Self> {
29        match value {
30            0 => Some(ColorLoopAction::Deactivate),
31            1 => Some(ColorLoopAction::Activatefromcolorloopstartenhancedhue),
32            2 => Some(ColorLoopAction::Activatefromenhancedcurrenthue),
33            _ => None,
34        }
35    }
36
37    /// Convert to u8 value
38    pub fn to_u8(self) -> u8 {
39        self as u8
40    }
41}
42
43impl From<ColorLoopAction> for u8 {
44    fn from(val: ColorLoopAction) -> Self {
45        val as u8
46    }
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
50#[repr(u8)]
51pub enum ColorLoopDirection {
52    /// Decrement the hue in the color loop.
53    Decrement = 0,
54    /// Increment the hue in the color loop.
55    Increment = 1,
56}
57
58impl ColorLoopDirection {
59    /// Convert from u8 value
60    pub fn from_u8(value: u8) -> Option<Self> {
61        match value {
62            0 => Some(ColorLoopDirection::Decrement),
63            1 => Some(ColorLoopDirection::Increment),
64            _ => None,
65        }
66    }
67
68    /// Convert to u8 value
69    pub fn to_u8(self) -> u8 {
70        self as u8
71    }
72}
73
74impl From<ColorLoopDirection> for u8 {
75    fn from(val: ColorLoopDirection) -> Self {
76        val as u8
77    }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
81#[repr(u8)]
82pub enum ColorMode {
83    /// The current hue and saturation attributes determine the color.
84    Currenthueandcurrentsaturation = 0,
85    /// The current X and Y attributes determine the color.
86    Currentxandcurrenty = 1,
87    /// The color temperature attribute determines the color.
88    Colortemperaturemireds = 2,
89}
90
91impl ColorMode {
92    /// Convert from u8 value
93    pub fn from_u8(value: u8) -> Option<Self> {
94        match value {
95            0 => Some(ColorMode::Currenthueandcurrentsaturation),
96            1 => Some(ColorMode::Currentxandcurrenty),
97            2 => Some(ColorMode::Colortemperaturemireds),
98            _ => None,
99        }
100    }
101
102    /// Convert to u8 value
103    pub fn to_u8(self) -> u8 {
104        self as u8
105    }
106}
107
108impl From<ColorMode> for u8 {
109    fn from(val: ColorMode) -> Self {
110        val as u8
111    }
112}
113
114#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
115#[repr(u8)]
116pub enum Direction {
117    /// Shortest distance
118    Shortest = 0,
119    /// Longest distance
120    Longest = 1,
121    /// Up
122    Up = 2,
123    /// Down
124    Down = 3,
125}
126
127impl Direction {
128    /// Convert from u8 value
129    pub fn from_u8(value: u8) -> Option<Self> {
130        match value {
131            0 => Some(Direction::Shortest),
132            1 => Some(Direction::Longest),
133            2 => Some(Direction::Up),
134            3 => Some(Direction::Down),
135            _ => None,
136        }
137    }
138
139    /// Convert to u8 value
140    pub fn to_u8(self) -> u8 {
141        self as u8
142    }
143}
144
145impl From<Direction> for u8 {
146    fn from(val: Direction) -> Self {
147        val as u8
148    }
149}
150
151#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
152#[repr(u8)]
153pub enum DriftCompensation {
154    /// There is no compensation.
155    None = 0,
156    /// The compensation is based on other or unknown mechanism.
157    Otherorunknown = 1,
158    /// The compensation is based on temperature monitoring.
159    Temperaturemonitoring = 2,
160    /// The compensation is based on optical luminance monitoring and feedback.
161    Opticalluminancemonitoringandfeedback = 3,
162    /// The compensation is based on optical color monitoring and feedback.
163    Opticalcolormonitoringandfeedback = 4,
164}
165
166impl DriftCompensation {
167    /// Convert from u8 value
168    pub fn from_u8(value: u8) -> Option<Self> {
169        match value {
170            0 => Some(DriftCompensation::None),
171            1 => Some(DriftCompensation::Otherorunknown),
172            2 => Some(DriftCompensation::Temperaturemonitoring),
173            3 => Some(DriftCompensation::Opticalluminancemonitoringandfeedback),
174            4 => Some(DriftCompensation::Opticalcolormonitoringandfeedback),
175            _ => None,
176        }
177    }
178
179    /// Convert to u8 value
180    pub fn to_u8(self) -> u8 {
181        self as u8
182    }
183}
184
185impl From<DriftCompensation> for u8 {
186    fn from(val: DriftCompensation) -> Self {
187        val as u8
188    }
189}
190
191#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
192#[repr(u8)]
193pub enum EnhancedColorMode {
194    /// The current hue and saturation attributes determine the color.
195    Currenthueandcurrentsaturation = 0,
196    /// The current X and Y attributes determine the color.
197    Currentxandcurrenty = 1,
198    /// The color temperature attribute determines the color.
199    Colortemperaturemireds = 2,
200    /// The enhanced current hue and saturation attributes determine the color.
201    Enhancedcurrenthueandcurrentsaturation = 3,
202}
203
204impl EnhancedColorMode {
205    /// Convert from u8 value
206    pub fn from_u8(value: u8) -> Option<Self> {
207        match value {
208            0 => Some(EnhancedColorMode::Currenthueandcurrentsaturation),
209            1 => Some(EnhancedColorMode::Currentxandcurrenty),
210            2 => Some(EnhancedColorMode::Colortemperaturemireds),
211            3 => Some(EnhancedColorMode::Enhancedcurrenthueandcurrentsaturation),
212            _ => None,
213        }
214    }
215
216    /// Convert to u8 value
217    pub fn to_u8(self) -> u8 {
218        self as u8
219    }
220}
221
222impl From<EnhancedColorMode> for u8 {
223    fn from(val: EnhancedColorMode) -> Self {
224        val as u8
225    }
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
229#[repr(u8)]
230pub enum MoveMode {
231    /// Stop the movement
232    Stop = 0,
233    /// Move in an upwards direction
234    Up = 1,
235    /// Move in a downwards direction
236    Down = 3,
237}
238
239impl MoveMode {
240    /// Convert from u8 value
241    pub fn from_u8(value: u8) -> Option<Self> {
242        match value {
243            0 => Some(MoveMode::Stop),
244            1 => Some(MoveMode::Up),
245            3 => Some(MoveMode::Down),
246            _ => None,
247        }
248    }
249
250    /// Convert to u8 value
251    pub fn to_u8(self) -> u8 {
252        self as u8
253    }
254}
255
256impl From<MoveMode> for u8 {
257    fn from(val: MoveMode) -> Self {
258        val as u8
259    }
260}
261
262#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
263#[repr(u8)]
264pub enum StepMode {
265    /// Step in an upwards direction
266    Up = 1,
267    /// Step in a downwards direction
268    Down = 3,
269}
270
271impl StepMode {
272    /// Convert from u8 value
273    pub fn from_u8(value: u8) -> Option<Self> {
274        match value {
275            1 => Some(StepMode::Up),
276            3 => Some(StepMode::Down),
277            _ => None,
278        }
279    }
280
281    /// Convert to u8 value
282    pub fn to_u8(self) -> u8 {
283        self as u8
284    }
285}
286
287impl From<StepMode> for u8 {
288    fn from(val: StepMode) -> Self {
289        val as u8
290    }
291}
292
293// Bitmap definitions
294
295/// ColorCapabilities bitmap type
296pub type ColorCapabilities = u8;
297
298/// Constants for ColorCapabilities
299pub mod colorcapabilities {
300    /// Supports color specification via hue/saturation.
301    pub const HUE_SATURATION: u8 = 0x01;
302    /// Enhanced hue is supported.
303    pub const ENHANCED_HUE: u8 = 0x02;
304    /// Color loop is supported.
305    pub const COLOR_LOOP: u8 = 0x04;
306    /// Supports color specification via XY.
307    pub const XY: u8 = 0x08;
308    /// Supports color specification via color temperature.
309    pub const COLOR_TEMPERATURE: u8 = 0x10;
310}
311
312/// Options bitmap type
313pub type Options = u8;
314
315/// Constants for Options
316pub mod options {
317    /// Dependency on On/Off cluster
318    pub const EXECUTE_IF_OFF: u8 = 0x01;
319}
320
321/// UpdateFlags bitmap type
322pub type UpdateFlags = u8;
323
324/// Constants for UpdateFlags
325pub mod updateflags {
326    /// Device adheres to the associated action field.
327    pub const UPDATE_ACTION: u8 = 0x01;
328    /// Device updates the associated direction attribute.
329    pub const UPDATE_DIRECTION: u8 = 0x02;
330    /// Device updates the associated time attribute.
331    pub const UPDATE_TIME: u8 = 0x04;
332    /// Device updates the associated start hue attribute.
333    pub const UPDATE_START_HUE: u8 = 0x08;
334}
335
336// Command encoders
337
338/// Encode MoveToHue command (0x00)
339pub fn encode_move_to_hue(hue: u8, direction: Direction, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
340    let tlv = tlv::TlvItemEnc {
341        tag: 0,
342        value: tlv::TlvItemValueEnc::StructInvisible(vec![
343        (0, tlv::TlvItemValueEnc::UInt8(hue)).into(),
344        (1, tlv::TlvItemValueEnc::UInt8(direction.to_u8())).into(),
345        (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
346        (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
347        (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
348        ]),
349    };
350    Ok(tlv.encode()?)
351}
352
353/// Encode MoveHue command (0x01)
354pub fn encode_move_hue(move_mode: MoveMode, rate: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
355    let tlv = tlv::TlvItemEnc {
356        tag: 0,
357        value: tlv::TlvItemValueEnc::StructInvisible(vec![
358        (0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
359        (1, tlv::TlvItemValueEnc::UInt8(rate)).into(),
360        (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
361        (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
362        ]),
363    };
364    Ok(tlv.encode()?)
365}
366
367/// Encode StepHue command (0x02)
368pub fn encode_step_hue(step_mode: StepMode, step_size: u8, transition_time: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
369    let tlv = tlv::TlvItemEnc {
370        tag: 0,
371        value: tlv::TlvItemValueEnc::StructInvisible(vec![
372        (0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
373        (1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
374        (2, tlv::TlvItemValueEnc::UInt8(transition_time)).into(),
375        (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
376        (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
377        ]),
378    };
379    Ok(tlv.encode()?)
380}
381
382/// Encode MoveToSaturation command (0x03)
383pub fn encode_move_to_saturation(saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
384    let tlv = tlv::TlvItemEnc {
385        tag: 0,
386        value: tlv::TlvItemValueEnc::StructInvisible(vec![
387        (0, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
388        (1, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
389        (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
390        (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
391        ]),
392    };
393    Ok(tlv.encode()?)
394}
395
396/// Encode MoveSaturation command (0x04)
397pub fn encode_move_saturation(move_mode: MoveMode, rate: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
398    let tlv = tlv::TlvItemEnc {
399        tag: 0,
400        value: tlv::TlvItemValueEnc::StructInvisible(vec![
401        (0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
402        (1, tlv::TlvItemValueEnc::UInt8(rate)).into(),
403        (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
404        (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
405        ]),
406    };
407    Ok(tlv.encode()?)
408}
409
410/// Encode StepSaturation command (0x05)
411pub fn encode_step_saturation(step_mode: StepMode, step_size: u8, transition_time: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
412    let tlv = tlv::TlvItemEnc {
413        tag: 0,
414        value: tlv::TlvItemValueEnc::StructInvisible(vec![
415        (0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
416        (1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
417        (2, tlv::TlvItemValueEnc::UInt8(transition_time)).into(),
418        (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
419        (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
420        ]),
421    };
422    Ok(tlv.encode()?)
423}
424
425/// Encode MoveToHueAndSaturation command (0x06)
426pub fn encode_move_to_hue_and_saturation(hue: u8, saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
427    let tlv = tlv::TlvItemEnc {
428        tag: 0,
429        value: tlv::TlvItemValueEnc::StructInvisible(vec![
430        (0, tlv::TlvItemValueEnc::UInt8(hue)).into(),
431        (1, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
432        (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
433        (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
434        (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
435        ]),
436    };
437    Ok(tlv.encode()?)
438}
439
440/// Encode MoveToColor command (0x07)
441pub fn encode_move_to_color(color_x: u16, color_y: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
442    let tlv = tlv::TlvItemEnc {
443        tag: 0,
444        value: tlv::TlvItemValueEnc::StructInvisible(vec![
445        (0, tlv::TlvItemValueEnc::UInt16(color_x)).into(),
446        (1, tlv::TlvItemValueEnc::UInt16(color_y)).into(),
447        (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
448        (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
449        (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
450        ]),
451    };
452    Ok(tlv.encode()?)
453}
454
455/// Encode MoveColor command (0x08)
456pub fn encode_move_color(rate_x: i16, rate_y: i16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
457    let tlv = tlv::TlvItemEnc {
458        tag: 0,
459        value: tlv::TlvItemValueEnc::StructInvisible(vec![
460        (0, tlv::TlvItemValueEnc::Int16(rate_x)).into(),
461        (1, tlv::TlvItemValueEnc::Int16(rate_y)).into(),
462        (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
463        (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
464        ]),
465    };
466    Ok(tlv.encode()?)
467}
468
469/// Encode StepColor command (0x09)
470pub fn encode_step_color(step_x: i16, step_y: i16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
471    let tlv = tlv::TlvItemEnc {
472        tag: 0,
473        value: tlv::TlvItemValueEnc::StructInvisible(vec![
474        (0, tlv::TlvItemValueEnc::Int16(step_x)).into(),
475        (1, tlv::TlvItemValueEnc::Int16(step_y)).into(),
476        (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
477        (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
478        (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
479        ]),
480    };
481    Ok(tlv.encode()?)
482}
483
484/// Encode MoveToColorTemperature command (0x0A)
485pub fn encode_move_to_color_temperature(color_temperature_mireds: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
486    let tlv = tlv::TlvItemEnc {
487        tag: 0,
488        value: tlv::TlvItemValueEnc::StructInvisible(vec![
489        (0, tlv::TlvItemValueEnc::UInt16(color_temperature_mireds)).into(),
490        (1, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
491        (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
492        (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
493        ]),
494    };
495    Ok(tlv.encode()?)
496}
497
498/// Encode EnhancedMoveToHue command (0x40)
499pub fn encode_enhanced_move_to_hue(enhanced_hue: u16, direction: Direction, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
500    let tlv = tlv::TlvItemEnc {
501        tag: 0,
502        value: tlv::TlvItemValueEnc::StructInvisible(vec![
503        (0, tlv::TlvItemValueEnc::UInt16(enhanced_hue)).into(),
504        (1, tlv::TlvItemValueEnc::UInt8(direction.to_u8())).into(),
505        (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
506        (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
507        (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
508        ]),
509    };
510    Ok(tlv.encode()?)
511}
512
513/// Encode EnhancedMoveHue command (0x41)
514pub fn encode_enhanced_move_hue(move_mode: MoveMode, rate: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
515    let tlv = tlv::TlvItemEnc {
516        tag: 0,
517        value: tlv::TlvItemValueEnc::StructInvisible(vec![
518        (0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
519        (1, tlv::TlvItemValueEnc::UInt16(rate)).into(),
520        (2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
521        (3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
522        ]),
523    };
524    Ok(tlv.encode()?)
525}
526
527/// Encode EnhancedStepHue command (0x42)
528pub fn encode_enhanced_step_hue(step_mode: StepMode, step_size: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
529    let tlv = tlv::TlvItemEnc {
530        tag: 0,
531        value: tlv::TlvItemValueEnc::StructInvisible(vec![
532        (0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
533        (1, tlv::TlvItemValueEnc::UInt16(step_size)).into(),
534        (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
535        (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
536        (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
537        ]),
538    };
539    Ok(tlv.encode()?)
540}
541
542/// Encode EnhancedMoveToHueAndSaturation command (0x43)
543pub 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>> {
544    let tlv = tlv::TlvItemEnc {
545        tag: 0,
546        value: tlv::TlvItemValueEnc::StructInvisible(vec![
547        (0, tlv::TlvItemValueEnc::UInt16(enhanced_hue)).into(),
548        (1, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
549        (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
550        (3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
551        (4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
552        ]),
553    };
554    Ok(tlv.encode()?)
555}
556
557/// Encode ColorLoopSet command (0x44)
558pub 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>> {
559    let tlv = tlv::TlvItemEnc {
560        tag: 0,
561        value: tlv::TlvItemValueEnc::StructInvisible(vec![
562        (0, tlv::TlvItemValueEnc::UInt8(update_flags)).into(),
563        (1, tlv::TlvItemValueEnc::UInt8(action.to_u8())).into(),
564        (2, tlv::TlvItemValueEnc::UInt8(direction.to_u8())).into(),
565        (3, tlv::TlvItemValueEnc::UInt16(time)).into(),
566        (4, tlv::TlvItemValueEnc::UInt16(start_hue)).into(),
567        (5, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
568        (6, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
569        ]),
570    };
571    Ok(tlv.encode()?)
572}
573
574/// Encode StopMoveStep command (0x47)
575pub fn encode_stop_move_step(options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
576    let tlv = tlv::TlvItemEnc {
577        tag: 0,
578        value: tlv::TlvItemValueEnc::StructInvisible(vec![
579        (0, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
580        (1, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
581        ]),
582    };
583    Ok(tlv.encode()?)
584}
585
586/// Encode MoveColorTemperature command (0x4B)
587pub 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>> {
588    let tlv = tlv::TlvItemEnc {
589        tag: 0,
590        value: tlv::TlvItemValueEnc::StructInvisible(vec![
591        (0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
592        (1, tlv::TlvItemValueEnc::UInt16(rate)).into(),
593        (2, tlv::TlvItemValueEnc::UInt16(color_temperature_minimum_mireds)).into(),
594        (3, tlv::TlvItemValueEnc::UInt16(color_temperature_maximum_mireds)).into(),
595        (4, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
596        (5, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
597        ]),
598    };
599    Ok(tlv.encode()?)
600}
601
602/// Encode StepColorTemperature command (0x4C)
603pub 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>> {
604    let tlv = tlv::TlvItemEnc {
605        tag: 0,
606        value: tlv::TlvItemValueEnc::StructInvisible(vec![
607        (0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
608        (1, tlv::TlvItemValueEnc::UInt16(step_size)).into(),
609        (2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
610        (3, tlv::TlvItemValueEnc::UInt16(color_temperature_minimum_mireds)).into(),
611        (4, tlv::TlvItemValueEnc::UInt16(color_temperature_maximum_mireds)).into(),
612        (5, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
613        (6, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
614        ]),
615    };
616    Ok(tlv.encode()?)
617}
618
619// Attribute decoders
620
621/// Decode CurrentHue attribute (0x0000)
622pub fn decode_current_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
623    if let tlv::TlvItemValue::Int(v) = inp {
624        Ok(*v as u8)
625    } else {
626        Err(anyhow::anyhow!("Expected UInt8"))
627    }
628}
629
630/// Decode CurrentSaturation attribute (0x0001)
631pub fn decode_current_saturation(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
632    if let tlv::TlvItemValue::Int(v) = inp {
633        Ok(*v as u8)
634    } else {
635        Err(anyhow::anyhow!("Expected UInt8"))
636    }
637}
638
639/// Decode RemainingTime attribute (0x0002)
640pub fn decode_remaining_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
641    if let tlv::TlvItemValue::Int(v) = inp {
642        Ok(*v as u16)
643    } else {
644        Err(anyhow::anyhow!("Expected UInt16"))
645    }
646}
647
648/// Decode CurrentX attribute (0x0003)
649pub fn decode_current_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
650    if let tlv::TlvItemValue::Int(v) = inp {
651        Ok(*v as u16)
652    } else {
653        Err(anyhow::anyhow!("Expected UInt16"))
654    }
655}
656
657/// Decode CurrentY attribute (0x0004)
658pub fn decode_current_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
659    if let tlv::TlvItemValue::Int(v) = inp {
660        Ok(*v as u16)
661    } else {
662        Err(anyhow::anyhow!("Expected UInt16"))
663    }
664}
665
666/// Decode DriftCompensation attribute (0x0005)
667pub fn decode_drift_compensation(inp: &tlv::TlvItemValue) -> anyhow::Result<DriftCompensation> {
668    if let tlv::TlvItemValue::Int(v) = inp {
669        DriftCompensation::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
670    } else {
671        Err(anyhow::anyhow!("Expected Integer"))
672    }
673}
674
675/// Decode CompensationText attribute (0x0006)
676pub fn decode_compensation_text(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
677    if let tlv::TlvItemValue::String(v) = inp {
678        Ok(v.clone())
679    } else {
680        Err(anyhow::anyhow!("Expected String"))
681    }
682}
683
684/// Decode ColorTemperatureMireds attribute (0x0007)
685pub fn decode_color_temperature_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
686    if let tlv::TlvItemValue::Int(v) = inp {
687        Ok(*v as u16)
688    } else {
689        Err(anyhow::anyhow!("Expected UInt16"))
690    }
691}
692
693/// Decode ColorMode attribute (0x0008)
694pub fn decode_color_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<ColorMode> {
695    if let tlv::TlvItemValue::Int(v) = inp {
696        ColorMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
697    } else {
698        Err(anyhow::anyhow!("Expected Integer"))
699    }
700}
701
702/// Decode Options attribute (0x000F)
703pub fn decode_options(inp: &tlv::TlvItemValue) -> anyhow::Result<Options> {
704    if let tlv::TlvItemValue::Int(v) = inp {
705        Ok(*v as u8)
706    } else {
707        Err(anyhow::anyhow!("Expected Integer"))
708    }
709}
710
711/// Decode NumberOfPrimaries attribute (0x0010)
712pub fn decode_number_of_primaries(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
713    if let tlv::TlvItemValue::Int(v) = inp {
714        Ok(Some(*v as u8))
715    } else {
716        Ok(None)
717    }
718}
719
720/// Decode Primary1X attribute (0x0011)
721pub fn decode_primary1_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
722    if let tlv::TlvItemValue::Int(v) = inp {
723        Ok(*v as u16)
724    } else {
725        Err(anyhow::anyhow!("Expected UInt16"))
726    }
727}
728
729/// Decode Primary1Y attribute (0x0012)
730pub fn decode_primary1_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
731    if let tlv::TlvItemValue::Int(v) = inp {
732        Ok(*v as u16)
733    } else {
734        Err(anyhow::anyhow!("Expected UInt16"))
735    }
736}
737
738/// Decode Primary1Intensity attribute (0x0013)
739pub fn decode_primary1_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
740    if let tlv::TlvItemValue::Int(v) = inp {
741        Ok(Some(*v as u8))
742    } else {
743        Ok(None)
744    }
745}
746
747/// Decode Primary2X attribute (0x0015)
748pub fn decode_primary2_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
749    if let tlv::TlvItemValue::Int(v) = inp {
750        Ok(*v as u16)
751    } else {
752        Err(anyhow::anyhow!("Expected UInt16"))
753    }
754}
755
756/// Decode Primary2Y attribute (0x0016)
757pub fn decode_primary2_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
758    if let tlv::TlvItemValue::Int(v) = inp {
759        Ok(*v as u16)
760    } else {
761        Err(anyhow::anyhow!("Expected UInt16"))
762    }
763}
764
765/// Decode Primary2Intensity attribute (0x0017)
766pub fn decode_primary2_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
767    if let tlv::TlvItemValue::Int(v) = inp {
768        Ok(Some(*v as u8))
769    } else {
770        Ok(None)
771    }
772}
773
774/// Decode Primary3X attribute (0x0019)
775pub fn decode_primary3_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
776    if let tlv::TlvItemValue::Int(v) = inp {
777        Ok(*v as u16)
778    } else {
779        Err(anyhow::anyhow!("Expected UInt16"))
780    }
781}
782
783/// Decode Primary3Y attribute (0x001A)
784pub fn decode_primary3_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
785    if let tlv::TlvItemValue::Int(v) = inp {
786        Ok(*v as u16)
787    } else {
788        Err(anyhow::anyhow!("Expected UInt16"))
789    }
790}
791
792/// Decode Primary3Intensity attribute (0x001B)
793pub fn decode_primary3_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
794    if let tlv::TlvItemValue::Int(v) = inp {
795        Ok(Some(*v as u8))
796    } else {
797        Ok(None)
798    }
799}
800
801/// Decode Primary4X attribute (0x0020)
802pub fn decode_primary4_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
803    if let tlv::TlvItemValue::Int(v) = inp {
804        Ok(*v as u16)
805    } else {
806        Err(anyhow::anyhow!("Expected UInt16"))
807    }
808}
809
810/// Decode Primary4Y attribute (0x0021)
811pub fn decode_primary4_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
812    if let tlv::TlvItemValue::Int(v) = inp {
813        Ok(*v as u16)
814    } else {
815        Err(anyhow::anyhow!("Expected UInt16"))
816    }
817}
818
819/// Decode Primary4Intensity attribute (0x0022)
820pub fn decode_primary4_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
821    if let tlv::TlvItemValue::Int(v) = inp {
822        Ok(Some(*v as u8))
823    } else {
824        Ok(None)
825    }
826}
827
828/// Decode Primary5X attribute (0x0024)
829pub fn decode_primary5_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
830    if let tlv::TlvItemValue::Int(v) = inp {
831        Ok(*v as u16)
832    } else {
833        Err(anyhow::anyhow!("Expected UInt16"))
834    }
835}
836
837/// Decode Primary5Y attribute (0x0025)
838pub fn decode_primary5_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
839    if let tlv::TlvItemValue::Int(v) = inp {
840        Ok(*v as u16)
841    } else {
842        Err(anyhow::anyhow!("Expected UInt16"))
843    }
844}
845
846/// Decode Primary5Intensity attribute (0x0026)
847pub fn decode_primary5_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
848    if let tlv::TlvItemValue::Int(v) = inp {
849        Ok(Some(*v as u8))
850    } else {
851        Ok(None)
852    }
853}
854
855/// Decode Primary6X attribute (0x0028)
856pub fn decode_primary6_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
857    if let tlv::TlvItemValue::Int(v) = inp {
858        Ok(*v as u16)
859    } else {
860        Err(anyhow::anyhow!("Expected UInt16"))
861    }
862}
863
864/// Decode Primary6Y attribute (0x0029)
865pub fn decode_primary6_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
866    if let tlv::TlvItemValue::Int(v) = inp {
867        Ok(*v as u16)
868    } else {
869        Err(anyhow::anyhow!("Expected UInt16"))
870    }
871}
872
873/// Decode Primary6Intensity attribute (0x002A)
874pub fn decode_primary6_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
875    if let tlv::TlvItemValue::Int(v) = inp {
876        Ok(Some(*v as u8))
877    } else {
878        Ok(None)
879    }
880}
881
882/// Decode WhitePointX attribute (0x0030)
883pub fn decode_white_point_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
884    if let tlv::TlvItemValue::Int(v) = inp {
885        Ok(*v as u16)
886    } else {
887        Err(anyhow::anyhow!("Expected UInt16"))
888    }
889}
890
891/// Decode WhitePointY attribute (0x0031)
892pub fn decode_white_point_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
893    if let tlv::TlvItemValue::Int(v) = inp {
894        Ok(*v as u16)
895    } else {
896        Err(anyhow::anyhow!("Expected UInt16"))
897    }
898}
899
900/// Decode ColorPointRX attribute (0x0032)
901pub fn decode_color_point_rx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
902    if let tlv::TlvItemValue::Int(v) = inp {
903        Ok(*v as u16)
904    } else {
905        Err(anyhow::anyhow!("Expected UInt16"))
906    }
907}
908
909/// Decode ColorPointRY attribute (0x0033)
910pub fn decode_color_point_ry(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
911    if let tlv::TlvItemValue::Int(v) = inp {
912        Ok(*v as u16)
913    } else {
914        Err(anyhow::anyhow!("Expected UInt16"))
915    }
916}
917
918/// Decode ColorPointRIntensity attribute (0x0034)
919pub fn decode_color_point_r_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
920    if let tlv::TlvItemValue::Int(v) = inp {
921        Ok(Some(*v as u8))
922    } else {
923        Ok(None)
924    }
925}
926
927/// Decode ColorPointGX attribute (0x0036)
928pub fn decode_color_point_gx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
929    if let tlv::TlvItemValue::Int(v) = inp {
930        Ok(*v as u16)
931    } else {
932        Err(anyhow::anyhow!("Expected UInt16"))
933    }
934}
935
936/// Decode ColorPointGY attribute (0x0037)
937pub fn decode_color_point_gy(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
938    if let tlv::TlvItemValue::Int(v) = inp {
939        Ok(*v as u16)
940    } else {
941        Err(anyhow::anyhow!("Expected UInt16"))
942    }
943}
944
945/// Decode ColorPointGIntensity attribute (0x0038)
946pub fn decode_color_point_g_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
947    if let tlv::TlvItemValue::Int(v) = inp {
948        Ok(Some(*v as u8))
949    } else {
950        Ok(None)
951    }
952}
953
954/// Decode ColorPointBX attribute (0x003A)
955pub fn decode_color_point_bx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
956    if let tlv::TlvItemValue::Int(v) = inp {
957        Ok(*v as u16)
958    } else {
959        Err(anyhow::anyhow!("Expected UInt16"))
960    }
961}
962
963/// Decode ColorPointBY attribute (0x003B)
964pub fn decode_color_point_by(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
965    if let tlv::TlvItemValue::Int(v) = inp {
966        Ok(*v as u16)
967    } else {
968        Err(anyhow::anyhow!("Expected UInt16"))
969    }
970}
971
972/// Decode ColorPointBIntensity attribute (0x003C)
973pub fn decode_color_point_b_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
974    if let tlv::TlvItemValue::Int(v) = inp {
975        Ok(Some(*v as u8))
976    } else {
977        Ok(None)
978    }
979}
980
981/// Decode EnhancedCurrentHue attribute (0x4000)
982pub fn decode_enhanced_current_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
983    if let tlv::TlvItemValue::Int(v) = inp {
984        Ok(*v as u16)
985    } else {
986        Err(anyhow::anyhow!("Expected UInt16"))
987    }
988}
989
990/// Decode EnhancedColorMode attribute (0x4001)
991pub fn decode_enhanced_color_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<EnhancedColorMode> {
992    if let tlv::TlvItemValue::Int(v) = inp {
993        EnhancedColorMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
994    } else {
995        Err(anyhow::anyhow!("Expected Integer"))
996    }
997}
998
999/// Decode ColorLoopActive attribute (0x4002)
1000pub fn decode_color_loop_active(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1001    if let tlv::TlvItemValue::Int(v) = inp {
1002        Ok(*v as u8)
1003    } else {
1004        Err(anyhow::anyhow!("Expected UInt8"))
1005    }
1006}
1007
1008/// Decode ColorLoopDirection attribute (0x4003)
1009pub fn decode_color_loop_direction(inp: &tlv::TlvItemValue) -> anyhow::Result<ColorLoopDirection> {
1010    if let tlv::TlvItemValue::Int(v) = inp {
1011        ColorLoopDirection::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1012    } else {
1013        Err(anyhow::anyhow!("Expected Integer"))
1014    }
1015}
1016
1017/// Decode ColorLoopTime attribute (0x4004)
1018pub fn decode_color_loop_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1019    if let tlv::TlvItemValue::Int(v) = inp {
1020        Ok(*v as u16)
1021    } else {
1022        Err(anyhow::anyhow!("Expected UInt16"))
1023    }
1024}
1025
1026/// Decode ColorLoopStartEnhancedHue attribute (0x4005)
1027pub fn decode_color_loop_start_enhanced_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1028    if let tlv::TlvItemValue::Int(v) = inp {
1029        Ok(*v as u16)
1030    } else {
1031        Err(anyhow::anyhow!("Expected UInt16"))
1032    }
1033}
1034
1035/// Decode ColorLoopStoredEnhancedHue attribute (0x4006)
1036pub fn decode_color_loop_stored_enhanced_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1037    if let tlv::TlvItemValue::Int(v) = inp {
1038        Ok(*v as u16)
1039    } else {
1040        Err(anyhow::anyhow!("Expected UInt16"))
1041    }
1042}
1043
1044/// Decode ColorCapabilities attribute (0x400A)
1045pub fn decode_color_capabilities(inp: &tlv::TlvItemValue) -> anyhow::Result<ColorCapabilities> {
1046    if let tlv::TlvItemValue::Int(v) = inp {
1047        Ok(*v as u8)
1048    } else {
1049        Err(anyhow::anyhow!("Expected Integer"))
1050    }
1051}
1052
1053/// Decode ColorTempPhysicalMinMireds attribute (0x400B)
1054pub fn decode_color_temp_physical_min_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1055    if let tlv::TlvItemValue::Int(v) = inp {
1056        Ok(*v as u16)
1057    } else {
1058        Err(anyhow::anyhow!("Expected UInt16"))
1059    }
1060}
1061
1062/// Decode ColorTempPhysicalMaxMireds attribute (0x400C)
1063pub fn decode_color_temp_physical_max_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1064    if let tlv::TlvItemValue::Int(v) = inp {
1065        Ok(*v as u16)
1066    } else {
1067        Err(anyhow::anyhow!("Expected UInt16"))
1068    }
1069}
1070
1071/// Decode CoupleColorTempToLevelMinMireds attribute (0x400D)
1072pub fn decode_couple_color_temp_to_level_min_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1073    if let tlv::TlvItemValue::Int(v) = inp {
1074        Ok(*v as u16)
1075    } else {
1076        Err(anyhow::anyhow!("Expected UInt16"))
1077    }
1078}
1079
1080/// Decode StartUpColorTemperatureMireds attribute (0x4010)
1081pub fn decode_start_up_color_temperature_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
1082    if let tlv::TlvItemValue::Int(v) = inp {
1083        Ok(Some(*v as u16))
1084    } else {
1085        Ok(None)
1086    }
1087}
1088
1089
1090// JSON dispatcher function
1091
1092/// Decode attribute value and return as JSON string
1093///
1094/// # Parameters
1095/// * `cluster_id` - The cluster identifier
1096/// * `attribute_id` - The attribute identifier
1097/// * `tlv_value` - The TLV value to decode
1098///
1099/// # Returns
1100/// JSON string representation of the decoded value or error
1101pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
1102    // Verify this is the correct cluster
1103    if cluster_id != 0x0300 {
1104        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0300, got {}\"}}", cluster_id);
1105    }
1106
1107    match attribute_id {
1108        0x0000 => {
1109            match decode_current_hue(tlv_value) {
1110                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1111                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1112            }
1113        }
1114        0x0001 => {
1115            match decode_current_saturation(tlv_value) {
1116                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1117                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1118            }
1119        }
1120        0x0002 => {
1121            match decode_remaining_time(tlv_value) {
1122                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1123                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1124            }
1125        }
1126        0x0003 => {
1127            match decode_current_x(tlv_value) {
1128                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1129                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1130            }
1131        }
1132        0x0004 => {
1133            match decode_current_y(tlv_value) {
1134                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1135                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1136            }
1137        }
1138        0x0005 => {
1139            match decode_drift_compensation(tlv_value) {
1140                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1141                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1142            }
1143        }
1144        0x0006 => {
1145            match decode_compensation_text(tlv_value) {
1146                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1147                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1148            }
1149        }
1150        0x0007 => {
1151            match decode_color_temperature_mireds(tlv_value) {
1152                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1153                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1154            }
1155        }
1156        0x0008 => {
1157            match decode_color_mode(tlv_value) {
1158                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1159                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1160            }
1161        }
1162        0x000F => {
1163            match decode_options(tlv_value) {
1164                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1165                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1166            }
1167        }
1168        0x0010 => {
1169            match decode_number_of_primaries(tlv_value) {
1170                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1171                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1172            }
1173        }
1174        0x0011 => {
1175            match decode_primary1_x(tlv_value) {
1176                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1177                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1178            }
1179        }
1180        0x0012 => {
1181            match decode_primary1_y(tlv_value) {
1182                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1183                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1184            }
1185        }
1186        0x0013 => {
1187            match decode_primary1_intensity(tlv_value) {
1188                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1189                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1190            }
1191        }
1192        0x0015 => {
1193            match decode_primary2_x(tlv_value) {
1194                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1195                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1196            }
1197        }
1198        0x0016 => {
1199            match decode_primary2_y(tlv_value) {
1200                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1201                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1202            }
1203        }
1204        0x0017 => {
1205            match decode_primary2_intensity(tlv_value) {
1206                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1207                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1208            }
1209        }
1210        0x0019 => {
1211            match decode_primary3_x(tlv_value) {
1212                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1213                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1214            }
1215        }
1216        0x001A => {
1217            match decode_primary3_y(tlv_value) {
1218                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1219                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1220            }
1221        }
1222        0x001B => {
1223            match decode_primary3_intensity(tlv_value) {
1224                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1225                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1226            }
1227        }
1228        0x0020 => {
1229            match decode_primary4_x(tlv_value) {
1230                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1231                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1232            }
1233        }
1234        0x0021 => {
1235            match decode_primary4_y(tlv_value) {
1236                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1237                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1238            }
1239        }
1240        0x0022 => {
1241            match decode_primary4_intensity(tlv_value) {
1242                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1243                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1244            }
1245        }
1246        0x0024 => {
1247            match decode_primary5_x(tlv_value) {
1248                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1249                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1250            }
1251        }
1252        0x0025 => {
1253            match decode_primary5_y(tlv_value) {
1254                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1255                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1256            }
1257        }
1258        0x0026 => {
1259            match decode_primary5_intensity(tlv_value) {
1260                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1261                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1262            }
1263        }
1264        0x0028 => {
1265            match decode_primary6_x(tlv_value) {
1266                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1267                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1268            }
1269        }
1270        0x0029 => {
1271            match decode_primary6_y(tlv_value) {
1272                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1273                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1274            }
1275        }
1276        0x002A => {
1277            match decode_primary6_intensity(tlv_value) {
1278                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1279                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1280            }
1281        }
1282        0x0030 => {
1283            match decode_white_point_x(tlv_value) {
1284                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1285                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1286            }
1287        }
1288        0x0031 => {
1289            match decode_white_point_y(tlv_value) {
1290                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1291                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1292            }
1293        }
1294        0x0032 => {
1295            match decode_color_point_rx(tlv_value) {
1296                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1297                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1298            }
1299        }
1300        0x0033 => {
1301            match decode_color_point_ry(tlv_value) {
1302                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1303                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1304            }
1305        }
1306        0x0034 => {
1307            match decode_color_point_r_intensity(tlv_value) {
1308                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1309                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1310            }
1311        }
1312        0x0036 => {
1313            match decode_color_point_gx(tlv_value) {
1314                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1315                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1316            }
1317        }
1318        0x0037 => {
1319            match decode_color_point_gy(tlv_value) {
1320                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1321                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1322            }
1323        }
1324        0x0038 => {
1325            match decode_color_point_g_intensity(tlv_value) {
1326                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1327                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1328            }
1329        }
1330        0x003A => {
1331            match decode_color_point_bx(tlv_value) {
1332                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1333                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1334            }
1335        }
1336        0x003B => {
1337            match decode_color_point_by(tlv_value) {
1338                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1339                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1340            }
1341        }
1342        0x003C => {
1343            match decode_color_point_b_intensity(tlv_value) {
1344                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1345                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1346            }
1347        }
1348        0x4000 => {
1349            match decode_enhanced_current_hue(tlv_value) {
1350                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1351                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1352            }
1353        }
1354        0x4001 => {
1355            match decode_enhanced_color_mode(tlv_value) {
1356                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1357                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1358            }
1359        }
1360        0x4002 => {
1361            match decode_color_loop_active(tlv_value) {
1362                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1363                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1364            }
1365        }
1366        0x4003 => {
1367            match decode_color_loop_direction(tlv_value) {
1368                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1369                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1370            }
1371        }
1372        0x4004 => {
1373            match decode_color_loop_time(tlv_value) {
1374                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1375                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1376            }
1377        }
1378        0x4005 => {
1379            match decode_color_loop_start_enhanced_hue(tlv_value) {
1380                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1381                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1382            }
1383        }
1384        0x4006 => {
1385            match decode_color_loop_stored_enhanced_hue(tlv_value) {
1386                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1387                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1388            }
1389        }
1390        0x400A => {
1391            match decode_color_capabilities(tlv_value) {
1392                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1393                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1394            }
1395        }
1396        0x400B => {
1397            match decode_color_temp_physical_min_mireds(tlv_value) {
1398                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1399                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1400            }
1401        }
1402        0x400C => {
1403            match decode_color_temp_physical_max_mireds(tlv_value) {
1404                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1405                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1406            }
1407        }
1408        0x400D => {
1409            match decode_couple_color_temp_to_level_min_mireds(tlv_value) {
1410                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1411                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1412            }
1413        }
1414        0x4010 => {
1415            match decode_start_up_color_temperature_mireds(tlv_value) {
1416                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1417                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1418            }
1419        }
1420        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1421    }
1422}
1423
1424/// Get list of all attributes supported by this cluster
1425///
1426/// # Returns
1427/// Vector of tuples containing (attribute_id, attribute_name)
1428pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1429    vec![
1430        (0x0000, "CurrentHue"),
1431        (0x0001, "CurrentSaturation"),
1432        (0x0002, "RemainingTime"),
1433        (0x0003, "CurrentX"),
1434        (0x0004, "CurrentY"),
1435        (0x0005, "DriftCompensation"),
1436        (0x0006, "CompensationText"),
1437        (0x0007, "ColorTemperatureMireds"),
1438        (0x0008, "ColorMode"),
1439        (0x000F, "Options"),
1440        (0x0010, "NumberOfPrimaries"),
1441        (0x0011, "Primary1X"),
1442        (0x0012, "Primary1Y"),
1443        (0x0013, "Primary1Intensity"),
1444        (0x0015, "Primary2X"),
1445        (0x0016, "Primary2Y"),
1446        (0x0017, "Primary2Intensity"),
1447        (0x0019, "Primary3X"),
1448        (0x001A, "Primary3Y"),
1449        (0x001B, "Primary3Intensity"),
1450        (0x0020, "Primary4X"),
1451        (0x0021, "Primary4Y"),
1452        (0x0022, "Primary4Intensity"),
1453        (0x0024, "Primary5X"),
1454        (0x0025, "Primary5Y"),
1455        (0x0026, "Primary5Intensity"),
1456        (0x0028, "Primary6X"),
1457        (0x0029, "Primary6Y"),
1458        (0x002A, "Primary6Intensity"),
1459        (0x0030, "WhitePointX"),
1460        (0x0031, "WhitePointY"),
1461        (0x0032, "ColorPointRX"),
1462        (0x0033, "ColorPointRY"),
1463        (0x0034, "ColorPointRIntensity"),
1464        (0x0036, "ColorPointGX"),
1465        (0x0037, "ColorPointGY"),
1466        (0x0038, "ColorPointGIntensity"),
1467        (0x003A, "ColorPointBX"),
1468        (0x003B, "ColorPointBY"),
1469        (0x003C, "ColorPointBIntensity"),
1470        (0x4000, "EnhancedCurrentHue"),
1471        (0x4001, "EnhancedColorMode"),
1472        (0x4002, "ColorLoopActive"),
1473        (0x4003, "ColorLoopDirection"),
1474        (0x4004, "ColorLoopTime"),
1475        (0x4005, "ColorLoopStartEnhancedHue"),
1476        (0x4006, "ColorLoopStoredEnhancedHue"),
1477        (0x400A, "ColorCapabilities"),
1478        (0x400B, "ColorTempPhysicalMinMireds"),
1479        (0x400C, "ColorTempPhysicalMaxMireds"),
1480        (0x400D, "CoupleColorTempToLevelMinMireds"),
1481        (0x4010, "StartUpColorTemperatureMireds"),
1482    ]
1483}
1484
1485// Command listing
1486
1487pub fn get_command_list() -> Vec<(u32, &'static str)> {
1488    vec![
1489        (0x00, "MoveToHue"),
1490        (0x01, "MoveHue"),
1491        (0x02, "StepHue"),
1492        (0x03, "MoveToSaturation"),
1493        (0x04, "MoveSaturation"),
1494        (0x05, "StepSaturation"),
1495        (0x06, "MoveToHueAndSaturation"),
1496        (0x07, "MoveToColor"),
1497        (0x08, "MoveColor"),
1498        (0x09, "StepColor"),
1499        (0x0A, "MoveToColorTemperature"),
1500        (0x40, "EnhancedMoveToHue"),
1501        (0x41, "EnhancedMoveHue"),
1502        (0x42, "EnhancedStepHue"),
1503        (0x43, "EnhancedMoveToHueAndSaturation"),
1504        (0x44, "ColorLoopSet"),
1505        (0x47, "StopMoveStep"),
1506        (0x4B, "MoveColorTemperature"),
1507        (0x4C, "StepColorTemperature"),
1508    ]
1509}
1510
1511pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
1512    match cmd_id {
1513        0x00 => Some("MoveToHue"),
1514        0x01 => Some("MoveHue"),
1515        0x02 => Some("StepHue"),
1516        0x03 => Some("MoveToSaturation"),
1517        0x04 => Some("MoveSaturation"),
1518        0x05 => Some("StepSaturation"),
1519        0x06 => Some("MoveToHueAndSaturation"),
1520        0x07 => Some("MoveToColor"),
1521        0x08 => Some("MoveColor"),
1522        0x09 => Some("StepColor"),
1523        0x0A => Some("MoveToColorTemperature"),
1524        0x40 => Some("EnhancedMoveToHue"),
1525        0x41 => Some("EnhancedMoveHue"),
1526        0x42 => Some("EnhancedStepHue"),
1527        0x43 => Some("EnhancedMoveToHueAndSaturation"),
1528        0x44 => Some("ColorLoopSet"),
1529        0x47 => Some("StopMoveStep"),
1530        0x4B => Some("MoveColorTemperature"),
1531        0x4C => Some("StepColorTemperature"),
1532        _ => None,
1533    }
1534}
1535
1536pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
1537    match cmd_id {
1538        0x00 => Some(vec![
1539            crate::clusters::codec::CommandField { tag: 0, name: "hue", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1540            crate::clusters::codec::CommandField { tag: 1, name: "direction", kind: crate::clusters::codec::FieldKind::Enum { name: "Direction", variants: &[(0, "Shortest"), (1, "Longest"), (2, "Up"), (3, "Down")] }, optional: false, nullable: false },
1541            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1542            crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1543            crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1544        ]),
1545        0x01 => Some(vec![
1546            crate::clusters::codec::CommandField { tag: 0, name: "move_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "MoveMode", variants: &[(0, "Stop"), (1, "Up"), (3, "Down")] }, optional: false, nullable: false },
1547            crate::clusters::codec::CommandField { tag: 1, name: "rate", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1548            crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1549            crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1550        ]),
1551        0x02 => Some(vec![
1552            crate::clusters::codec::CommandField { tag: 0, name: "step_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "StepMode", variants: &[(1, "Up"), (3, "Down")] }, optional: false, nullable: false },
1553            crate::clusters::codec::CommandField { tag: 1, name: "step_size", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1554            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1555            crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1556            crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1557        ]),
1558        0x03 => Some(vec![
1559            crate::clusters::codec::CommandField { tag: 0, name: "saturation", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1560            crate::clusters::codec::CommandField { tag: 1, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1561            crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1562            crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1563        ]),
1564        0x04 => Some(vec![
1565            crate::clusters::codec::CommandField { tag: 0, name: "move_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "MoveMode", variants: &[(0, "Stop"), (1, "Up"), (3, "Down")] }, optional: false, nullable: false },
1566            crate::clusters::codec::CommandField { tag: 1, name: "rate", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1567            crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1568            crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1569        ]),
1570        0x05 => Some(vec![
1571            crate::clusters::codec::CommandField { tag: 0, name: "step_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "StepMode", variants: &[(1, "Up"), (3, "Down")] }, optional: false, nullable: false },
1572            crate::clusters::codec::CommandField { tag: 1, name: "step_size", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1573            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1574            crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1575            crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1576        ]),
1577        0x06 => Some(vec![
1578            crate::clusters::codec::CommandField { tag: 0, name: "hue", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1579            crate::clusters::codec::CommandField { tag: 1, name: "saturation", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1580            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1581            crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1582            crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1583        ]),
1584        0x07 => Some(vec![
1585            crate::clusters::codec::CommandField { tag: 0, name: "color_x", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1586            crate::clusters::codec::CommandField { tag: 1, name: "color_y", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1587            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1588            crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1589            crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1590        ]),
1591        0x08 => Some(vec![
1592            crate::clusters::codec::CommandField { tag: 0, name: "rate_x", kind: crate::clusters::codec::FieldKind::I16, optional: false, nullable: false },
1593            crate::clusters::codec::CommandField { tag: 1, name: "rate_y", kind: crate::clusters::codec::FieldKind::I16, optional: false, nullable: false },
1594            crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1595            crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1596        ]),
1597        0x09 => Some(vec![
1598            crate::clusters::codec::CommandField { tag: 0, name: "step_x", kind: crate::clusters::codec::FieldKind::I16, optional: false, nullable: false },
1599            crate::clusters::codec::CommandField { tag: 1, name: "step_y", kind: crate::clusters::codec::FieldKind::I16, optional: false, nullable: false },
1600            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1601            crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1602            crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1603        ]),
1604        0x0A => Some(vec![
1605            crate::clusters::codec::CommandField { tag: 0, name: "color_temperature_mireds", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1606            crate::clusters::codec::CommandField { tag: 1, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1607            crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1608            crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1609        ]),
1610        0x40 => Some(vec![
1611            crate::clusters::codec::CommandField { tag: 0, name: "enhanced_hue", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1612            crate::clusters::codec::CommandField { tag: 1, name: "direction", kind: crate::clusters::codec::FieldKind::Enum { name: "Direction", variants: &[(0, "Shortest"), (1, "Longest"), (2, "Up"), (3, "Down")] }, optional: false, nullable: false },
1613            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1614            crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1615            crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1616        ]),
1617        0x41 => Some(vec![
1618            crate::clusters::codec::CommandField { tag: 0, name: "move_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "MoveMode", variants: &[(0, "Stop"), (1, "Up"), (3, "Down")] }, optional: false, nullable: false },
1619            crate::clusters::codec::CommandField { tag: 1, name: "rate", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1620            crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1621            crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1622        ]),
1623        0x42 => Some(vec![
1624            crate::clusters::codec::CommandField { tag: 0, name: "step_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "StepMode", variants: &[(1, "Up"), (3, "Down")] }, optional: false, nullable: false },
1625            crate::clusters::codec::CommandField { tag: 1, name: "step_size", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1626            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1627            crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1628            crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1629        ]),
1630        0x43 => Some(vec![
1631            crate::clusters::codec::CommandField { tag: 0, name: "enhanced_hue", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1632            crate::clusters::codec::CommandField { tag: 1, name: "saturation", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
1633            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1634            crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1635            crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1636        ]),
1637        0x44 => Some(vec![
1638            crate::clusters::codec::CommandField { tag: 0, name: "update_flags", kind: crate::clusters::codec::FieldKind::Bitmap { name: "UpdateFlags", bits: &[(1, "UPDATE_ACTION"), (2, "UPDATE_DIRECTION"), (4, "UPDATE_TIME"), (8, "UPDATE_START_HUE")] }, optional: false, nullable: false },
1639            crate::clusters::codec::CommandField { tag: 1, name: "action", kind: crate::clusters::codec::FieldKind::Enum { name: "ColorLoopAction", variants: &[(0, "Deactivate"), (1, "Activatefromcolorloopstartenhancedhue"), (2, "Activatefromenhancedcurrenthue")] }, optional: false, nullable: false },
1640            crate::clusters::codec::CommandField { tag: 2, name: "direction", kind: crate::clusters::codec::FieldKind::Enum { name: "ColorLoopDirection", variants: &[(0, "Decrement"), (1, "Increment")] }, optional: false, nullable: false },
1641            crate::clusters::codec::CommandField { tag: 3, name: "time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1642            crate::clusters::codec::CommandField { tag: 4, name: "start_hue", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1643            crate::clusters::codec::CommandField { tag: 5, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1644            crate::clusters::codec::CommandField { tag: 6, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1645        ]),
1646        0x47 => Some(vec![
1647            crate::clusters::codec::CommandField { tag: 0, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1648            crate::clusters::codec::CommandField { tag: 1, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1649        ]),
1650        0x4B => Some(vec![
1651            crate::clusters::codec::CommandField { tag: 0, name: "move_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "MoveMode", variants: &[(0, "Stop"), (1, "Up"), (3, "Down")] }, optional: false, nullable: false },
1652            crate::clusters::codec::CommandField { tag: 1, name: "rate", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1653            crate::clusters::codec::CommandField { tag: 2, name: "color_temperature_minimum_mireds", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1654            crate::clusters::codec::CommandField { tag: 3, name: "color_temperature_maximum_mireds", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1655            crate::clusters::codec::CommandField { tag: 4, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1656            crate::clusters::codec::CommandField { tag: 5, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1657        ]),
1658        0x4C => Some(vec![
1659            crate::clusters::codec::CommandField { tag: 0, name: "step_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "StepMode", variants: &[(1, "Up"), (3, "Down")] }, optional: false, nullable: false },
1660            crate::clusters::codec::CommandField { tag: 1, name: "step_size", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1661            crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1662            crate::clusters::codec::CommandField { tag: 3, name: "color_temperature_minimum_mireds", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1663            crate::clusters::codec::CommandField { tag: 4, name: "color_temperature_maximum_mireds", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
1664            crate::clusters::codec::CommandField { tag: 5, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1665            crate::clusters::codec::CommandField { tag: 6, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF")] }, optional: false, nullable: false },
1666        ]),
1667        _ => None,
1668    }
1669}
1670
1671pub fn encode_command_json(cmd_id: u32, args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
1672    match cmd_id {
1673        0x00 => {
1674        let hue = crate::clusters::codec::json_util::get_u8(args, "hue")?;
1675        let direction = {
1676            let n = crate::clusters::codec::json_util::get_u64(args, "direction")?;
1677            Direction::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid Direction: {}", n))?
1678        };
1679        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1680        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1681        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1682        encode_move_to_hue(hue, direction, transition_time, options_mask, options_override)
1683        }
1684        0x01 => {
1685        let move_mode = {
1686            let n = crate::clusters::codec::json_util::get_u64(args, "move_mode")?;
1687            MoveMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid MoveMode: {}", n))?
1688        };
1689        let rate = crate::clusters::codec::json_util::get_u8(args, "rate")?;
1690        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1691        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1692        encode_move_hue(move_mode, rate, options_mask, options_override)
1693        }
1694        0x02 => {
1695        let step_mode = {
1696            let n = crate::clusters::codec::json_util::get_u64(args, "step_mode")?;
1697            StepMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid StepMode: {}", n))?
1698        };
1699        let step_size = crate::clusters::codec::json_util::get_u8(args, "step_size")?;
1700        let transition_time = crate::clusters::codec::json_util::get_u8(args, "transition_time")?;
1701        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1702        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1703        encode_step_hue(step_mode, step_size, transition_time, options_mask, options_override)
1704        }
1705        0x03 => {
1706        let saturation = crate::clusters::codec::json_util::get_u8(args, "saturation")?;
1707        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1708        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1709        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1710        encode_move_to_saturation(saturation, transition_time, options_mask, options_override)
1711        }
1712        0x04 => {
1713        let move_mode = {
1714            let n = crate::clusters::codec::json_util::get_u64(args, "move_mode")?;
1715            MoveMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid MoveMode: {}", n))?
1716        };
1717        let rate = crate::clusters::codec::json_util::get_u8(args, "rate")?;
1718        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1719        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1720        encode_move_saturation(move_mode, rate, options_mask, options_override)
1721        }
1722        0x05 => {
1723        let step_mode = {
1724            let n = crate::clusters::codec::json_util::get_u64(args, "step_mode")?;
1725            StepMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid StepMode: {}", n))?
1726        };
1727        let step_size = crate::clusters::codec::json_util::get_u8(args, "step_size")?;
1728        let transition_time = crate::clusters::codec::json_util::get_u8(args, "transition_time")?;
1729        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1730        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1731        encode_step_saturation(step_mode, step_size, transition_time, options_mask, options_override)
1732        }
1733        0x06 => {
1734        let hue = crate::clusters::codec::json_util::get_u8(args, "hue")?;
1735        let saturation = crate::clusters::codec::json_util::get_u8(args, "saturation")?;
1736        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1737        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1738        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1739        encode_move_to_hue_and_saturation(hue, saturation, transition_time, options_mask, options_override)
1740        }
1741        0x07 => {
1742        let color_x = crate::clusters::codec::json_util::get_u16(args, "color_x")?;
1743        let color_y = crate::clusters::codec::json_util::get_u16(args, "color_y")?;
1744        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1745        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1746        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1747        encode_move_to_color(color_x, color_y, transition_time, options_mask, options_override)
1748        }
1749        0x08 => {
1750        let rate_x = crate::clusters::codec::json_util::get_i16(args, "rate_x")?;
1751        let rate_y = crate::clusters::codec::json_util::get_i16(args, "rate_y")?;
1752        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1753        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1754        encode_move_color(rate_x, rate_y, options_mask, options_override)
1755        }
1756        0x09 => {
1757        let step_x = crate::clusters::codec::json_util::get_i16(args, "step_x")?;
1758        let step_y = crate::clusters::codec::json_util::get_i16(args, "step_y")?;
1759        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1760        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1761        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1762        encode_step_color(step_x, step_y, transition_time, options_mask, options_override)
1763        }
1764        0x0A => {
1765        let color_temperature_mireds = crate::clusters::codec::json_util::get_u16(args, "color_temperature_mireds")?;
1766        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1767        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1768        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1769        encode_move_to_color_temperature(color_temperature_mireds, transition_time, options_mask, options_override)
1770        }
1771        0x40 => {
1772        let enhanced_hue = crate::clusters::codec::json_util::get_u16(args, "enhanced_hue")?;
1773        let direction = {
1774            let n = crate::clusters::codec::json_util::get_u64(args, "direction")?;
1775            Direction::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid Direction: {}", n))?
1776        };
1777        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1778        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1779        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1780        encode_enhanced_move_to_hue(enhanced_hue, direction, transition_time, options_mask, options_override)
1781        }
1782        0x41 => {
1783        let move_mode = {
1784            let n = crate::clusters::codec::json_util::get_u64(args, "move_mode")?;
1785            MoveMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid MoveMode: {}", n))?
1786        };
1787        let rate = crate::clusters::codec::json_util::get_u16(args, "rate")?;
1788        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1789        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1790        encode_enhanced_move_hue(move_mode, rate, options_mask, options_override)
1791        }
1792        0x42 => {
1793        let step_mode = {
1794            let n = crate::clusters::codec::json_util::get_u64(args, "step_mode")?;
1795            StepMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid StepMode: {}", n))?
1796        };
1797        let step_size = crate::clusters::codec::json_util::get_u16(args, "step_size")?;
1798        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1799        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1800        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1801        encode_enhanced_step_hue(step_mode, step_size, transition_time, options_mask, options_override)
1802        }
1803        0x43 => {
1804        let enhanced_hue = crate::clusters::codec::json_util::get_u16(args, "enhanced_hue")?;
1805        let saturation = crate::clusters::codec::json_util::get_u8(args, "saturation")?;
1806        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1807        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1808        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1809        encode_enhanced_move_to_hue_and_saturation(enhanced_hue, saturation, transition_time, options_mask, options_override)
1810        }
1811        0x44 => {
1812        let update_flags = crate::clusters::codec::json_util::get_u8(args, "update_flags")?;
1813        let action = {
1814            let n = crate::clusters::codec::json_util::get_u64(args, "action")?;
1815            ColorLoopAction::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid ColorLoopAction: {}", n))?
1816        };
1817        let direction = {
1818            let n = crate::clusters::codec::json_util::get_u64(args, "direction")?;
1819            ColorLoopDirection::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid ColorLoopDirection: {}", n))?
1820        };
1821        let time = crate::clusters::codec::json_util::get_u16(args, "time")?;
1822        let start_hue = crate::clusters::codec::json_util::get_u16(args, "start_hue")?;
1823        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1824        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1825        encode_color_loop_set(update_flags, action, direction, time, start_hue, options_mask, options_override)
1826        }
1827        0x47 => {
1828        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1829        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1830        encode_stop_move_step(options_mask, options_override)
1831        }
1832        0x4B => {
1833        let move_mode = {
1834            let n = crate::clusters::codec::json_util::get_u64(args, "move_mode")?;
1835            MoveMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid MoveMode: {}", n))?
1836        };
1837        let rate = crate::clusters::codec::json_util::get_u16(args, "rate")?;
1838        let color_temperature_minimum_mireds = crate::clusters::codec::json_util::get_u16(args, "color_temperature_minimum_mireds")?;
1839        let color_temperature_maximum_mireds = crate::clusters::codec::json_util::get_u16(args, "color_temperature_maximum_mireds")?;
1840        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1841        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1842        encode_move_color_temperature(move_mode, rate, color_temperature_minimum_mireds, color_temperature_maximum_mireds, options_mask, options_override)
1843        }
1844        0x4C => {
1845        let step_mode = {
1846            let n = crate::clusters::codec::json_util::get_u64(args, "step_mode")?;
1847            StepMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid StepMode: {}", n))?
1848        };
1849        let step_size = crate::clusters::codec::json_util::get_u16(args, "step_size")?;
1850        let transition_time = crate::clusters::codec::json_util::get_u16(args, "transition_time")?;
1851        let color_temperature_minimum_mireds = crate::clusters::codec::json_util::get_u16(args, "color_temperature_minimum_mireds")?;
1852        let color_temperature_maximum_mireds = crate::clusters::codec::json_util::get_u16(args, "color_temperature_maximum_mireds")?;
1853        let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
1854        let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
1855        encode_step_color_temperature(step_mode, step_size, transition_time, color_temperature_minimum_mireds, color_temperature_maximum_mireds, options_mask, options_override)
1856        }
1857        _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
1858    }
1859}
1860
1861// Typed facade (invokes + reads)
1862
1863/// Invoke `MoveToHue` command on cluster `Color Control`.
1864pub async fn move_to_hue(conn: &crate::controller::Connection, endpoint: u16, hue: u8, direction: Direction, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1865    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_MOVETOHUE, &encode_move_to_hue(hue, direction, transition_time, options_mask, options_override)?).await?;
1866    Ok(())
1867}
1868
1869/// Invoke `MoveHue` command on cluster `Color Control`.
1870pub async fn move_hue(conn: &crate::controller::Connection, endpoint: u16, move_mode: MoveMode, rate: u8, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1871    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_MOVEHUE, &encode_move_hue(move_mode, rate, options_mask, options_override)?).await?;
1872    Ok(())
1873}
1874
1875/// Invoke `StepHue` command on cluster `Color Control`.
1876pub async fn step_hue(conn: &crate::controller::Connection, endpoint: u16, step_mode: StepMode, step_size: u8, transition_time: u8, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1877    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_STEPHUE, &encode_step_hue(step_mode, step_size, transition_time, options_mask, options_override)?).await?;
1878    Ok(())
1879}
1880
1881/// Invoke `MoveToSaturation` command on cluster `Color Control`.
1882pub async fn move_to_saturation(conn: &crate::controller::Connection, endpoint: u16, saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1883    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_MOVETOSATURATION, &encode_move_to_saturation(saturation, transition_time, options_mask, options_override)?).await?;
1884    Ok(())
1885}
1886
1887/// Invoke `MoveSaturation` command on cluster `Color Control`.
1888pub async fn move_saturation(conn: &crate::controller::Connection, endpoint: u16, move_mode: MoveMode, rate: u8, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1889    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_MOVESATURATION, &encode_move_saturation(move_mode, rate, options_mask, options_override)?).await?;
1890    Ok(())
1891}
1892
1893/// Invoke `StepSaturation` command on cluster `Color Control`.
1894pub async fn step_saturation(conn: &crate::controller::Connection, endpoint: u16, step_mode: StepMode, step_size: u8, transition_time: u8, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1895    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_STEPSATURATION, &encode_step_saturation(step_mode, step_size, transition_time, options_mask, options_override)?).await?;
1896    Ok(())
1897}
1898
1899/// Invoke `MoveToHueAndSaturation` command on cluster `Color Control`.
1900pub async fn move_to_hue_and_saturation(conn: &crate::controller::Connection, endpoint: u16, hue: u8, saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1901    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_MOVETOHUEANDSATURATION, &encode_move_to_hue_and_saturation(hue, saturation, transition_time, options_mask, options_override)?).await?;
1902    Ok(())
1903}
1904
1905/// Invoke `MoveToColor` command on cluster `Color Control`.
1906pub async fn move_to_color(conn: &crate::controller::Connection, endpoint: u16, color_x: u16, color_y: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1907    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_MOVETOCOLOR, &encode_move_to_color(color_x, color_y, transition_time, options_mask, options_override)?).await?;
1908    Ok(())
1909}
1910
1911/// Invoke `MoveColor` command on cluster `Color Control`.
1912pub async fn move_color(conn: &crate::controller::Connection, endpoint: u16, rate_x: i16, rate_y: i16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1913    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_MOVECOLOR, &encode_move_color(rate_x, rate_y, options_mask, options_override)?).await?;
1914    Ok(())
1915}
1916
1917/// Invoke `StepColor` command on cluster `Color Control`.
1918pub async fn step_color(conn: &crate::controller::Connection, endpoint: u16, step_x: i16, step_y: i16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1919    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_STEPCOLOR, &encode_step_color(step_x, step_y, transition_time, options_mask, options_override)?).await?;
1920    Ok(())
1921}
1922
1923/// Invoke `MoveToColorTemperature` command on cluster `Color Control`.
1924pub async fn move_to_color_temperature(conn: &crate::controller::Connection, endpoint: u16, color_temperature_mireds: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1925    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_MOVETOCOLORTEMPERATURE, &encode_move_to_color_temperature(color_temperature_mireds, transition_time, options_mask, options_override)?).await?;
1926    Ok(())
1927}
1928
1929/// Invoke `EnhancedMoveToHue` command on cluster `Color Control`.
1930pub async fn enhanced_move_to_hue(conn: &crate::controller::Connection, endpoint: u16, enhanced_hue: u16, direction: Direction, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1931    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_ENHANCEDMOVETOHUE, &encode_enhanced_move_to_hue(enhanced_hue, direction, transition_time, options_mask, options_override)?).await?;
1932    Ok(())
1933}
1934
1935/// Invoke `EnhancedMoveHue` command on cluster `Color Control`.
1936pub async fn enhanced_move_hue(conn: &crate::controller::Connection, endpoint: u16, move_mode: MoveMode, rate: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1937    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_ENHANCEDMOVEHUE, &encode_enhanced_move_hue(move_mode, rate, options_mask, options_override)?).await?;
1938    Ok(())
1939}
1940
1941/// Invoke `EnhancedStepHue` command on cluster `Color Control`.
1942pub async fn enhanced_step_hue(conn: &crate::controller::Connection, endpoint: u16, step_mode: StepMode, step_size: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1943    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_ENHANCEDSTEPHUE, &encode_enhanced_step_hue(step_mode, step_size, transition_time, options_mask, options_override)?).await?;
1944    Ok(())
1945}
1946
1947/// Invoke `EnhancedMoveToHueAndSaturation` command on cluster `Color Control`.
1948pub async fn enhanced_move_to_hue_and_saturation(conn: &crate::controller::Connection, endpoint: u16, enhanced_hue: u16, saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1949    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_ENHANCEDMOVETOHUEANDSATURATION, &encode_enhanced_move_to_hue_and_saturation(enhanced_hue, saturation, transition_time, options_mask, options_override)?).await?;
1950    Ok(())
1951}
1952
1953/// Invoke `ColorLoopSet` command on cluster `Color Control`.
1954pub async fn color_loop_set(conn: &crate::controller::Connection, endpoint: u16, update_flags: UpdateFlags, action: ColorLoopAction, direction: ColorLoopDirection, time: u16, start_hue: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1955    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_COLORLOOPSET, &encode_color_loop_set(update_flags, action, direction, time, start_hue, options_mask, options_override)?).await?;
1956    Ok(())
1957}
1958
1959/// Invoke `StopMoveStep` command on cluster `Color Control`.
1960pub async fn stop_move_step(conn: &crate::controller::Connection, endpoint: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1961    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_STOPMOVESTEP, &encode_stop_move_step(options_mask, options_override)?).await?;
1962    Ok(())
1963}
1964
1965/// Invoke `MoveColorTemperature` command on cluster `Color Control`.
1966pub async fn move_color_temperature(conn: &crate::controller::Connection, endpoint: u16, move_mode: MoveMode, rate: u16, color_temperature_minimum_mireds: u16, color_temperature_maximum_mireds: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
1967    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_MOVECOLORTEMPERATURE, &encode_move_color_temperature(move_mode, rate, color_temperature_minimum_mireds, color_temperature_maximum_mireds, options_mask, options_override)?).await?;
1968    Ok(())
1969}
1970
1971/// Invoke `StepColorTemperature` command on cluster `Color Control`.
1972pub async fn step_color_temperature(conn: &crate::controller::Connection, endpoint: u16, 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<()> {
1973    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_CMD_ID_STEPCOLORTEMPERATURE, &encode_step_color_temperature(step_mode, step_size, transition_time, color_temperature_minimum_mireds, color_temperature_maximum_mireds, options_mask, options_override)?).await?;
1974    Ok(())
1975}
1976
1977/// Read `CurrentHue` attribute from cluster `Color Control`.
1978pub async fn read_current_hue(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
1979    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_CURRENTHUE).await?;
1980    decode_current_hue(&tlv)
1981}
1982
1983/// Read `CurrentSaturation` attribute from cluster `Color Control`.
1984pub async fn read_current_saturation(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
1985    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_CURRENTSATURATION).await?;
1986    decode_current_saturation(&tlv)
1987}
1988
1989/// Read `RemainingTime` attribute from cluster `Color Control`.
1990pub async fn read_remaining_time(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1991    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_REMAININGTIME).await?;
1992    decode_remaining_time(&tlv)
1993}
1994
1995/// Read `CurrentX` attribute from cluster `Color Control`.
1996pub async fn read_current_x(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1997    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_CURRENTX).await?;
1998    decode_current_x(&tlv)
1999}
2000
2001/// Read `CurrentY` attribute from cluster `Color Control`.
2002pub async fn read_current_y(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2003    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_CURRENTY).await?;
2004    decode_current_y(&tlv)
2005}
2006
2007/// Read `DriftCompensation` attribute from cluster `Color Control`.
2008pub async fn read_drift_compensation(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<DriftCompensation> {
2009    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_DRIFTCOMPENSATION).await?;
2010    decode_drift_compensation(&tlv)
2011}
2012
2013/// Read `CompensationText` attribute from cluster `Color Control`.
2014pub async fn read_compensation_text(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
2015    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COMPENSATIONTEXT).await?;
2016    decode_compensation_text(&tlv)
2017}
2018
2019/// Read `ColorTemperatureMireds` attribute from cluster `Color Control`.
2020pub async fn read_color_temperature_mireds(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2021    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORTEMPERATUREMIREDS).await?;
2022    decode_color_temperature_mireds(&tlv)
2023}
2024
2025/// Read `ColorMode` attribute from cluster `Color Control`.
2026pub async fn read_color_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<ColorMode> {
2027    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORMODE).await?;
2028    decode_color_mode(&tlv)
2029}
2030
2031/// Read `Options` attribute from cluster `Color Control`.
2032pub async fn read_options(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Options> {
2033    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_OPTIONS).await?;
2034    decode_options(&tlv)
2035}
2036
2037/// Read `NumberOfPrimaries` attribute from cluster `Color Control`.
2038pub async fn read_number_of_primaries(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2039    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_NUMBEROFPRIMARIES).await?;
2040    decode_number_of_primaries(&tlv)
2041}
2042
2043/// Read `Primary1X` attribute from cluster `Color Control`.
2044pub async fn read_primary1_x(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2045    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY1X).await?;
2046    decode_primary1_x(&tlv)
2047}
2048
2049/// Read `Primary1Y` attribute from cluster `Color Control`.
2050pub async fn read_primary1_y(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2051    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY1Y).await?;
2052    decode_primary1_y(&tlv)
2053}
2054
2055/// Read `Primary1Intensity` attribute from cluster `Color Control`.
2056pub async fn read_primary1_intensity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2057    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY1INTENSITY).await?;
2058    decode_primary1_intensity(&tlv)
2059}
2060
2061/// Read `Primary2X` attribute from cluster `Color Control`.
2062pub async fn read_primary2_x(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2063    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY2X).await?;
2064    decode_primary2_x(&tlv)
2065}
2066
2067/// Read `Primary2Y` attribute from cluster `Color Control`.
2068pub async fn read_primary2_y(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2069    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY2Y).await?;
2070    decode_primary2_y(&tlv)
2071}
2072
2073/// Read `Primary2Intensity` attribute from cluster `Color Control`.
2074pub async fn read_primary2_intensity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2075    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY2INTENSITY).await?;
2076    decode_primary2_intensity(&tlv)
2077}
2078
2079/// Read `Primary3X` attribute from cluster `Color Control`.
2080pub async fn read_primary3_x(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2081    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY3X).await?;
2082    decode_primary3_x(&tlv)
2083}
2084
2085/// Read `Primary3Y` attribute from cluster `Color Control`.
2086pub async fn read_primary3_y(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2087    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY3Y).await?;
2088    decode_primary3_y(&tlv)
2089}
2090
2091/// Read `Primary3Intensity` attribute from cluster `Color Control`.
2092pub async fn read_primary3_intensity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2093    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY3INTENSITY).await?;
2094    decode_primary3_intensity(&tlv)
2095}
2096
2097/// Read `Primary4X` attribute from cluster `Color Control`.
2098pub async fn read_primary4_x(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2099    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY4X).await?;
2100    decode_primary4_x(&tlv)
2101}
2102
2103/// Read `Primary4Y` attribute from cluster `Color Control`.
2104pub async fn read_primary4_y(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2105    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY4Y).await?;
2106    decode_primary4_y(&tlv)
2107}
2108
2109/// Read `Primary4Intensity` attribute from cluster `Color Control`.
2110pub async fn read_primary4_intensity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2111    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY4INTENSITY).await?;
2112    decode_primary4_intensity(&tlv)
2113}
2114
2115/// Read `Primary5X` attribute from cluster `Color Control`.
2116pub async fn read_primary5_x(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2117    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY5X).await?;
2118    decode_primary5_x(&tlv)
2119}
2120
2121/// Read `Primary5Y` attribute from cluster `Color Control`.
2122pub async fn read_primary5_y(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2123    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY5Y).await?;
2124    decode_primary5_y(&tlv)
2125}
2126
2127/// Read `Primary5Intensity` attribute from cluster `Color Control`.
2128pub async fn read_primary5_intensity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2129    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY5INTENSITY).await?;
2130    decode_primary5_intensity(&tlv)
2131}
2132
2133/// Read `Primary6X` attribute from cluster `Color Control`.
2134pub async fn read_primary6_x(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2135    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY6X).await?;
2136    decode_primary6_x(&tlv)
2137}
2138
2139/// Read `Primary6Y` attribute from cluster `Color Control`.
2140pub async fn read_primary6_y(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2141    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY6Y).await?;
2142    decode_primary6_y(&tlv)
2143}
2144
2145/// Read `Primary6Intensity` attribute from cluster `Color Control`.
2146pub async fn read_primary6_intensity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2147    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_PRIMARY6INTENSITY).await?;
2148    decode_primary6_intensity(&tlv)
2149}
2150
2151/// Read `WhitePointX` attribute from cluster `Color Control`.
2152pub async fn read_white_point_x(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2153    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_WHITEPOINTX).await?;
2154    decode_white_point_x(&tlv)
2155}
2156
2157/// Read `WhitePointY` attribute from cluster `Color Control`.
2158pub async fn read_white_point_y(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2159    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_WHITEPOINTY).await?;
2160    decode_white_point_y(&tlv)
2161}
2162
2163/// Read `ColorPointRX` attribute from cluster `Color Control`.
2164pub async fn read_color_point_rx(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2165    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORPOINTRX).await?;
2166    decode_color_point_rx(&tlv)
2167}
2168
2169/// Read `ColorPointRY` attribute from cluster `Color Control`.
2170pub async fn read_color_point_ry(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2171    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORPOINTRY).await?;
2172    decode_color_point_ry(&tlv)
2173}
2174
2175/// Read `ColorPointRIntensity` attribute from cluster `Color Control`.
2176pub async fn read_color_point_r_intensity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2177    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORPOINTRINTENSITY).await?;
2178    decode_color_point_r_intensity(&tlv)
2179}
2180
2181/// Read `ColorPointGX` attribute from cluster `Color Control`.
2182pub async fn read_color_point_gx(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2183    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORPOINTGX).await?;
2184    decode_color_point_gx(&tlv)
2185}
2186
2187/// Read `ColorPointGY` attribute from cluster `Color Control`.
2188pub async fn read_color_point_gy(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2189    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORPOINTGY).await?;
2190    decode_color_point_gy(&tlv)
2191}
2192
2193/// Read `ColorPointGIntensity` attribute from cluster `Color Control`.
2194pub async fn read_color_point_g_intensity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2195    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORPOINTGINTENSITY).await?;
2196    decode_color_point_g_intensity(&tlv)
2197}
2198
2199/// Read `ColorPointBX` attribute from cluster `Color Control`.
2200pub async fn read_color_point_bx(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2201    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORPOINTBX).await?;
2202    decode_color_point_bx(&tlv)
2203}
2204
2205/// Read `ColorPointBY` attribute from cluster `Color Control`.
2206pub async fn read_color_point_by(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2207    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORPOINTBY).await?;
2208    decode_color_point_by(&tlv)
2209}
2210
2211/// Read `ColorPointBIntensity` attribute from cluster `Color Control`.
2212pub async fn read_color_point_b_intensity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
2213    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORPOINTBINTENSITY).await?;
2214    decode_color_point_b_intensity(&tlv)
2215}
2216
2217/// Read `EnhancedCurrentHue` attribute from cluster `Color Control`.
2218pub async fn read_enhanced_current_hue(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2219    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_ENHANCEDCURRENTHUE).await?;
2220    decode_enhanced_current_hue(&tlv)
2221}
2222
2223/// Read `EnhancedColorMode` attribute from cluster `Color Control`.
2224pub async fn read_enhanced_color_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<EnhancedColorMode> {
2225    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_ENHANCEDCOLORMODE).await?;
2226    decode_enhanced_color_mode(&tlv)
2227}
2228
2229/// Read `ColorLoopActive` attribute from cluster `Color Control`.
2230pub async fn read_color_loop_active(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2231    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORLOOPACTIVE).await?;
2232    decode_color_loop_active(&tlv)
2233}
2234
2235/// Read `ColorLoopDirection` attribute from cluster `Color Control`.
2236pub async fn read_color_loop_direction(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<ColorLoopDirection> {
2237    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORLOOPDIRECTION).await?;
2238    decode_color_loop_direction(&tlv)
2239}
2240
2241/// Read `ColorLoopTime` attribute from cluster `Color Control`.
2242pub async fn read_color_loop_time(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2243    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORLOOPTIME).await?;
2244    decode_color_loop_time(&tlv)
2245}
2246
2247/// Read `ColorLoopStartEnhancedHue` attribute from cluster `Color Control`.
2248pub async fn read_color_loop_start_enhanced_hue(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2249    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORLOOPSTARTENHANCEDHUE).await?;
2250    decode_color_loop_start_enhanced_hue(&tlv)
2251}
2252
2253/// Read `ColorLoopStoredEnhancedHue` attribute from cluster `Color Control`.
2254pub async fn read_color_loop_stored_enhanced_hue(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2255    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORLOOPSTOREDENHANCEDHUE).await?;
2256    decode_color_loop_stored_enhanced_hue(&tlv)
2257}
2258
2259/// Read `ColorCapabilities` attribute from cluster `Color Control`.
2260pub async fn read_color_capabilities(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<ColorCapabilities> {
2261    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORCAPABILITIES).await?;
2262    decode_color_capabilities(&tlv)
2263}
2264
2265/// Read `ColorTempPhysicalMinMireds` attribute from cluster `Color Control`.
2266pub async fn read_color_temp_physical_min_mireds(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2267    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORTEMPPHYSICALMINMIREDS).await?;
2268    decode_color_temp_physical_min_mireds(&tlv)
2269}
2270
2271/// Read `ColorTempPhysicalMaxMireds` attribute from cluster `Color Control`.
2272pub async fn read_color_temp_physical_max_mireds(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2273    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COLORTEMPPHYSICALMAXMIREDS).await?;
2274    decode_color_temp_physical_max_mireds(&tlv)
2275}
2276
2277/// Read `CoupleColorTempToLevelMinMireds` attribute from cluster `Color Control`.
2278pub async fn read_couple_color_temp_to_level_min_mireds(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2279    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_COUPLECOLORTEMPTOLEVELMINMIREDS).await?;
2280    decode_couple_color_temp_to_level_min_mireds(&tlv)
2281}
2282
2283/// Read `StartUpColorTemperatureMireds` attribute from cluster `Color Control`.
2284pub async fn read_start_up_color_temperature_mireds(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
2285    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COLOR_CONTROL, crate::clusters::defs::CLUSTER_COLOR_CONTROL_ATTR_ID_STARTUPCOLORTEMPERATUREMIREDS).await?;
2286    decode_start_up_color_temperature_mireds(&tlv)
2287}
2288