use crate::tlv;
use anyhow;
use serde_json;
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum ColorLoopAction {
Deactivate = 0,
Activatefromcolorloopstartenhancedhue = 1,
Activatefromenhancedcurrenthue = 2,
}
impl ColorLoopAction {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(ColorLoopAction::Deactivate),
1 => Some(ColorLoopAction::Activatefromcolorloopstartenhancedhue),
2 => Some(ColorLoopAction::Activatefromenhancedcurrenthue),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<ColorLoopAction> for u8 {
fn from(val: ColorLoopAction) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum ColorLoopDirection {
Decrement = 0,
Increment = 1,
}
impl ColorLoopDirection {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(ColorLoopDirection::Decrement),
1 => Some(ColorLoopDirection::Increment),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<ColorLoopDirection> for u8 {
fn from(val: ColorLoopDirection) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum ColorMode {
Currenthueandcurrentsaturation = 0,
Currentxandcurrenty = 1,
Colortemperaturemireds = 2,
}
impl ColorMode {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(ColorMode::Currenthueandcurrentsaturation),
1 => Some(ColorMode::Currentxandcurrenty),
2 => Some(ColorMode::Colortemperaturemireds),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<ColorMode> for u8 {
fn from(val: ColorMode) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum Direction {
Shortest = 0,
Longest = 1,
Up = 2,
Down = 3,
}
impl Direction {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(Direction::Shortest),
1 => Some(Direction::Longest),
2 => Some(Direction::Up),
3 => Some(Direction::Down),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<Direction> for u8 {
fn from(val: Direction) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum DriftCompensation {
None = 0,
Otherorunknown = 1,
Temperaturemonitoring = 2,
Opticalluminancemonitoringandfeedback = 3,
Opticalcolormonitoringandfeedback = 4,
}
impl DriftCompensation {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(DriftCompensation::None),
1 => Some(DriftCompensation::Otherorunknown),
2 => Some(DriftCompensation::Temperaturemonitoring),
3 => Some(DriftCompensation::Opticalluminancemonitoringandfeedback),
4 => Some(DriftCompensation::Opticalcolormonitoringandfeedback),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<DriftCompensation> for u8 {
fn from(val: DriftCompensation) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum EnhancedColorMode {
Currenthueandcurrentsaturation = 0,
Currentxandcurrenty = 1,
Colortemperaturemireds = 2,
Enhancedcurrenthueandcurrentsaturation = 3,
}
impl EnhancedColorMode {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(EnhancedColorMode::Currenthueandcurrentsaturation),
1 => Some(EnhancedColorMode::Currentxandcurrenty),
2 => Some(EnhancedColorMode::Colortemperaturemireds),
3 => Some(EnhancedColorMode::Enhancedcurrenthueandcurrentsaturation),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<EnhancedColorMode> for u8 {
fn from(val: EnhancedColorMode) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum MoveMode {
Stop = 0,
Up = 1,
Down = 3,
}
impl MoveMode {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(MoveMode::Stop),
1 => Some(MoveMode::Up),
3 => Some(MoveMode::Down),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<MoveMode> for u8 {
fn from(val: MoveMode) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum StepMode {
Up = 1,
Down = 3,
}
impl StepMode {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
1 => Some(StepMode::Up),
3 => Some(StepMode::Down),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<StepMode> for u8 {
fn from(val: StepMode) -> Self {
val as u8
}
}
pub type ColorCapabilities = u8;
pub mod colorcapabilities {
pub const HUE_SATURATION: u8 = 0x01;
pub const ENHANCED_HUE: u8 = 0x02;
pub const COLOR_LOOP: u8 = 0x04;
pub const XY: u8 = 0x08;
pub const COLOR_TEMPERATURE: u8 = 0x10;
}
pub type Options = u8;
pub mod options {
pub const EXECUTE_IF_OFF: u8 = 0x01;
}
pub type UpdateFlags = u8;
pub mod updateflags {
pub const UPDATE_ACTION: u8 = 0x01;
pub const UPDATE_DIRECTION: u8 = 0x02;
pub const UPDATE_TIME: u8 = 0x04;
pub const UPDATE_START_HUE: u8 = 0x08;
}
pub fn encode_move_to_hue(hue: u8, direction: Direction, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(hue)).into(),
(1, tlv::TlvItemValueEnc::UInt8(direction.to_u8())).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_hue(move_mode: MoveMode, rate: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt8(rate)).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_step_hue(step_mode: StepMode, step_size: u8, transition_time: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
(2, tlv::TlvItemValueEnc::UInt8(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_to_saturation(saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
(1, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_saturation(move_mode: MoveMode, rate: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt8(rate)).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_step_saturation(step_mode: StepMode, step_size: u8, transition_time: u8, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
(2, tlv::TlvItemValueEnc::UInt8(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_to_hue_and_saturation(hue: u8, saturation: u8, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(hue)).into(),
(1, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_to_color(color_x: u16, color_y: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt16(color_x)).into(),
(1, tlv::TlvItemValueEnc::UInt16(color_y)).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_color(rate_x: i16, rate_y: i16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::Int16(rate_x)).into(),
(1, tlv::TlvItemValueEnc::Int16(rate_y)).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_step_color(step_x: i16, step_y: i16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::Int16(step_x)).into(),
(1, tlv::TlvItemValueEnc::Int16(step_y)).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_to_color_temperature(color_temperature_mireds: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt16(color_temperature_mireds)).into(),
(1, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_enhanced_move_to_hue(enhanced_hue: u16, direction: Direction, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt16(enhanced_hue)).into(),
(1, tlv::TlvItemValueEnc::UInt8(direction.to_u8())).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_enhanced_move_hue(move_mode: MoveMode, rate: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt16(rate)).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_enhanced_step_hue(step_mode: StepMode, step_size: u16, transition_time: u16, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt16(step_size)).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub 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>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt16(enhanced_hue)).into(),
(1, tlv::TlvItemValueEnc::UInt8(saturation)).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub 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>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(update_flags)).into(),
(1, tlv::TlvItemValueEnc::UInt8(action.to_u8())).into(),
(2, tlv::TlvItemValueEnc::UInt8(direction.to_u8())).into(),
(3, tlv::TlvItemValueEnc::UInt16(time)).into(),
(4, tlv::TlvItemValueEnc::UInt16(start_hue)).into(),
(5, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(6, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_stop_move_step(options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(1, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub 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>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt16(rate)).into(),
(2, tlv::TlvItemValueEnc::UInt16(color_temperature_minimum_mireds)).into(),
(3, tlv::TlvItemValueEnc::UInt16(color_temperature_maximum_mireds)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(5, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub 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>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt16(step_size)).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time)).into(),
(3, tlv::TlvItemValueEnc::UInt16(color_temperature_minimum_mireds)).into(),
(4, tlv::TlvItemValueEnc::UInt16(color_temperature_maximum_mireds)).into(),
(5, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(6, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn decode_current_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u8)
} else {
Err(anyhow::anyhow!("Expected UInt8"))
}
}
pub fn decode_current_saturation(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u8)
} else {
Err(anyhow::anyhow!("Expected UInt8"))
}
}
pub fn decode_remaining_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_current_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_current_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_drift_compensation(inp: &tlv::TlvItemValue) -> anyhow::Result<DriftCompensation> {
if let tlv::TlvItemValue::Int(v) = inp {
DriftCompensation::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_compensation_text(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_color_temperature_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<ColorMode> {
if let tlv::TlvItemValue::Int(v) = inp {
ColorMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_options(inp: &tlv::TlvItemValue) -> anyhow::Result<Options> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u8)
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_number_of_primaries(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_primary1_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary1_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary1_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_primary2_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary2_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary2_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_primary3_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary3_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary3_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_primary4_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary4_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary4_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_primary5_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary5_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary5_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_primary6_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary6_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_primary6_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_white_point_x(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_white_point_y(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_point_rx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_point_ry(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_point_r_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_color_point_gx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_point_gy(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_point_g_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_color_point_bx(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_point_by(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_point_b_intensity(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_enhanced_current_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_enhanced_color_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<EnhancedColorMode> {
if let tlv::TlvItemValue::Int(v) = inp {
EnhancedColorMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_color_loop_active(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u8)
} else {
Err(anyhow::anyhow!("Expected UInt8"))
}
}
pub fn decode_color_loop_direction(inp: &tlv::TlvItemValue) -> anyhow::Result<ColorLoopDirection> {
if let tlv::TlvItemValue::Int(v) = inp {
ColorLoopDirection::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_color_loop_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_loop_start_enhanced_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_loop_stored_enhanced_hue(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_capabilities(inp: &tlv::TlvItemValue) -> anyhow::Result<ColorCapabilities> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u8)
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_color_temp_physical_min_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_color_temp_physical_max_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_couple_color_temp_to_level_min_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_start_up_color_temperature_mireds(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u16))
} else {
Ok(None)
}
}
pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
if cluster_id != 0x0300 {
return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0300, got {}\"}}", cluster_id);
}
match attribute_id {
0x0000 => {
match decode_current_hue(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0001 => {
match decode_current_saturation(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0002 => {
match decode_remaining_time(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0003 => {
match decode_current_x(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0004 => {
match decode_current_y(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0005 => {
match decode_drift_compensation(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0006 => {
match decode_compensation_text(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0007 => {
match decode_color_temperature_mireds(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0008 => {
match decode_color_mode(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000F => {
match decode_options(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0010 => {
match decode_number_of_primaries(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0011 => {
match decode_primary1_x(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0012 => {
match decode_primary1_y(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0013 => {
match decode_primary1_intensity(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0015 => {
match decode_primary2_x(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0016 => {
match decode_primary2_y(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0017 => {
match decode_primary2_intensity(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0019 => {
match decode_primary3_x(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x001A => {
match decode_primary3_y(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x001B => {
match decode_primary3_intensity(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0020 => {
match decode_primary4_x(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0021 => {
match decode_primary4_y(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0022 => {
match decode_primary4_intensity(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0024 => {
match decode_primary5_x(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0025 => {
match decode_primary5_y(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0026 => {
match decode_primary5_intensity(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0028 => {
match decode_primary6_x(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0029 => {
match decode_primary6_y(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x002A => {
match decode_primary6_intensity(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0030 => {
match decode_white_point_x(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0031 => {
match decode_white_point_y(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0032 => {
match decode_color_point_rx(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0033 => {
match decode_color_point_ry(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0034 => {
match decode_color_point_r_intensity(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0036 => {
match decode_color_point_gx(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0037 => {
match decode_color_point_gy(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0038 => {
match decode_color_point_g_intensity(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x003A => {
match decode_color_point_bx(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x003B => {
match decode_color_point_by(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x003C => {
match decode_color_point_b_intensity(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x4000 => {
match decode_enhanced_current_hue(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x4001 => {
match decode_enhanced_color_mode(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x4002 => {
match decode_color_loop_active(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x4003 => {
match decode_color_loop_direction(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x4004 => {
match decode_color_loop_time(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x4005 => {
match decode_color_loop_start_enhanced_hue(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x4006 => {
match decode_color_loop_stored_enhanced_hue(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x400A => {
match decode_color_capabilities(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x400B => {
match decode_color_temp_physical_min_mireds(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x400C => {
match decode_color_temp_physical_max_mireds(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x400D => {
match decode_couple_color_temp_to_level_min_mireds(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x4010 => {
match decode_start_up_color_temperature_mireds(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
_ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
}
}
pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
vec![
(0x0000, "CurrentHue"),
(0x0001, "CurrentSaturation"),
(0x0002, "RemainingTime"),
(0x0003, "CurrentX"),
(0x0004, "CurrentY"),
(0x0005, "DriftCompensation"),
(0x0006, "CompensationText"),
(0x0007, "ColorTemperatureMireds"),
(0x0008, "ColorMode"),
(0x000F, "Options"),
(0x0010, "NumberOfPrimaries"),
(0x0011, "Primary1X"),
(0x0012, "Primary1Y"),
(0x0013, "Primary1Intensity"),
(0x0015, "Primary2X"),
(0x0016, "Primary2Y"),
(0x0017, "Primary2Intensity"),
(0x0019, "Primary3X"),
(0x001A, "Primary3Y"),
(0x001B, "Primary3Intensity"),
(0x0020, "Primary4X"),
(0x0021, "Primary4Y"),
(0x0022, "Primary4Intensity"),
(0x0024, "Primary5X"),
(0x0025, "Primary5Y"),
(0x0026, "Primary5Intensity"),
(0x0028, "Primary6X"),
(0x0029, "Primary6Y"),
(0x002A, "Primary6Intensity"),
(0x0030, "WhitePointX"),
(0x0031, "WhitePointY"),
(0x0032, "ColorPointRX"),
(0x0033, "ColorPointRY"),
(0x0034, "ColorPointRIntensity"),
(0x0036, "ColorPointGX"),
(0x0037, "ColorPointGY"),
(0x0038, "ColorPointGIntensity"),
(0x003A, "ColorPointBX"),
(0x003B, "ColorPointBY"),
(0x003C, "ColorPointBIntensity"),
(0x4000, "EnhancedCurrentHue"),
(0x4001, "EnhancedColorMode"),
(0x4002, "ColorLoopActive"),
(0x4003, "ColorLoopDirection"),
(0x4004, "ColorLoopTime"),
(0x4005, "ColorLoopStartEnhancedHue"),
(0x4006, "ColorLoopStoredEnhancedHue"),
(0x400A, "ColorCapabilities"),
(0x400B, "ColorTempPhysicalMinMireds"),
(0x400C, "ColorTempPhysicalMaxMireds"),
(0x400D, "CoupleColorTempToLevelMinMireds"),
(0x4010, "StartUpColorTemperatureMireds"),
]
}