huesmith-core 0.1.0

Platform-agnostic core for Hue-compatible Zigbee lights: color math, ZCL light state machine, and scene parsing
Documentation
// ZCL profile and device IDs (ZigBee Cluster Library spec, table 5-2)
pub const PROFILE_HA: u16 = 0x0104;

pub const DEVICE_ON_OFF_LIGHT: u16 = 0x0100;
pub const DEVICE_DIMMABLE_LIGHT: u16 = 0x0101;
pub const DEVICE_COLOR_TEMPERATURE_LIGHT: u16 = 0x010C;
pub const DEVICE_EXTENDED_COLOR_LIGHT: u16 = 0x010D;

// Color capability bitmask (ZCL Color Control cluster, attr 0x400A)
pub const COLOR_CAP_HUE_SAT: u16 = 0x0001;
pub const COLOR_CAP_ENHANCED_HUE: u16 = 0x0002;
pub const COLOR_CAP_COLOR_LOOP: u16 = 0x0004;
pub const COLOR_CAP_XY: u16 = 0x0008;
pub const COLOR_CAP_COLOR_TEMP: u16 = 0x0010;
/// All capabilities. Only use this if you implement the ColorLoopSet ZCL command.
pub const COLOR_CAP_ALL: u16 = 0x001F;
/// Full color without color loop. Use for WS2812B lights that support hue, XY, and CCT
/// but do not implement the ColorLoopSet command handler.
pub const COLOR_CAP_FULL_NO_LOOP: u16 =
    COLOR_CAP_HUE_SAT | COLOR_CAP_ENHANCED_HUE | COLOR_CAP_XY | COLOR_CAP_COLOR_TEMP;

/// Hue-compatible device types with their ZCL device IDs and capabilities.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum HueDeviceType {
    /// Full RGB + Color Temperature (e.g., Hue White and Color Ambiance).
    ExtendedColorLight,
    /// Color Temperature only (e.g., Hue White Ambiance).
    ColorTemperatureLight,
    /// Dimmable only (e.g., Hue White).
    DimmableLight,
    /// On/Off only — no dimming or color.
    OnOffLight,
}

impl HueDeviceType {
    /// The ZCL/HA device identifier advertised in the endpoint's Simple
    /// Descriptor (e.g. `0x010D` for an Extended Color Light).
    pub fn device_id(self) -> u16 {
        match self {
            Self::ExtendedColorLight => DEVICE_EXTENDED_COLOR_LIGHT,
            Self::ColorTemperatureLight => DEVICE_COLOR_TEMPERATURE_LIGHT,
            Self::DimmableLight => DEVICE_DIMMABLE_LIGHT,
            Self::OnOffLight => DEVICE_ON_OFF_LIGHT,
        }
    }

    /// Whether this device type exposes the Level Control cluster (everything
    /// except a bare on/off light).
    pub fn has_level_control(self) -> bool {
        !matches!(self, Self::OnOffLight)
    }

    /// Whether this device type exposes the Color Control cluster (extended
    /// color and color-temperature lights).
    pub fn has_color_control(self) -> bool {
        matches!(self, Self::ExtendedColorLight | Self::ColorTemperatureLight)
    }

    /// Whether this device type drives full RGB color (extended color light
    /// only); a color-temperature light has Color Control but no RGB.
    pub fn has_rgb(self) -> bool {
        matches!(self, Self::ExtendedColorLight)
    }

    /// Color control parameters: `(capabilities, min_mireds, max_mireds)`.
    pub fn color_params(self) -> (u16, u16, u16) {
        match self {
            Self::ExtendedColorLight => (COLOR_CAP_FULL_NO_LOOP, 153, 500),
            Self::ColorTemperatureLight => (COLOR_CAP_COLOR_TEMP, 153, 454),
            Self::DimmableLight | Self::OnOffLight => (0, 0, 0),
        }
    }
}