From 2ea604cc2a73bfdd19bfe0b0c1ca71f1a370ad3a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 15 Sep 2020 02:27:30 -0500 Subject: [PATCH] Convert color temperature to hue and saturation for HomeKit (#40089) The HomeKit spec does not permit the color temp characteristic being exposed when color (hue, sat) is present. Since Home Assistant will still send color temp values, we need to convert them to hue, sat values for HomeKit --- homeassistant/components/homekit/type_lights.py | 17 ++++++++++++++--- tests/components/homekit/test_type_lights.py | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index 612d8e53a02..086934ea6f7 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -24,6 +24,10 @@ from homeassistant.const import ( STATE_ON, ) from homeassistant.core import callback +from homeassistant.util.color import ( + color_temperature_mired_to_kelvin, + color_temperature_to_hs, +) from .accessories import TYPES, HomeAccessory from .const import ( @@ -64,8 +68,6 @@ class Light(HomeAccessory): if self._features & SUPPORT_COLOR: self.chars.append(CHAR_HUE) self.chars.append(CHAR_SATURATION) - self._hue = None - self._saturation = None elif self._features & SUPPORT_COLOR_TEMP: # ColorTemperature and Hue characteristic should not be # exposed both. Both states are tracked separately in HomeKit, @@ -179,7 +181,16 @@ class Light(HomeAccessory): # Handle Color if CHAR_SATURATION in self.chars and CHAR_HUE in self.chars: - hue, saturation = new_state.attributes.get(ATTR_HS_COLOR, (None, None)) + if ATTR_HS_COLOR in new_state.attributes: + hue, saturation = new_state.attributes[ATTR_HS_COLOR] + elif ATTR_COLOR_TEMP in new_state.attributes: + hue, saturation = color_temperature_to_hs( + color_temperature_mired_to_kelvin( + new_state.attributes[ATTR_COLOR_TEMP] + ) + ) + else: + hue, saturation = None, None if isinstance(hue, (int, float)) and isinstance(saturation, (int, float)): hue = round(hue, 0) saturation = round(saturation, 0) diff --git a/tests/components/homekit/test_type_lights.py b/tests/components/homekit/test_type_lights.py index 20029861adb..e82bc5bb15d 100644 --- a/tests/components/homekit/test_type_lights.py +++ b/tests/components/homekit/test_type_lights.py @@ -293,9 +293,25 @@ async def test_light_color_temperature_and_rgb_color(hass, hk_driver, cls, event ) await hass.async_block_till_done() acc = cls.light(hass, hk_driver, "Light", entity_id, 2, None) + assert acc.char_hue.value == 260 + assert acc.char_saturation.value == 90 assert not hasattr(acc, "char_color_temperature") + hass.states.async_set(entity_id, STATE_ON, {ATTR_COLOR_TEMP: 224}) + await hass.async_block_till_done() + await acc.run_handler() + await hass.async_block_till_done() + assert acc.char_hue.value == 27 + assert acc.char_saturation.value == 27 + + hass.states.async_set(entity_id, STATE_ON, {ATTR_COLOR_TEMP: 352}) + await hass.async_block_till_done() + await acc.run_handler() + await hass.async_block_till_done() + assert acc.char_hue.value == 28 + assert acc.char_saturation.value == 61 + async def test_light_rgb_color(hass, hk_driver, cls, events): """Test light with rgb_color."""