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
This commit is contained in:
J. Nick Koston 2020-09-15 02:27:30 -05:00 committed by GitHub
parent 8d687c951a
commit 2ea604cc2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 3 deletions

View file

@ -24,6 +24,10 @@ from homeassistant.const import (
STATE_ON, STATE_ON,
) )
from homeassistant.core import callback 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 .accessories import TYPES, HomeAccessory
from .const import ( from .const import (
@ -64,8 +68,6 @@ class Light(HomeAccessory):
if self._features & SUPPORT_COLOR: if self._features & SUPPORT_COLOR:
self.chars.append(CHAR_HUE) self.chars.append(CHAR_HUE)
self.chars.append(CHAR_SATURATION) self.chars.append(CHAR_SATURATION)
self._hue = None
self._saturation = None
elif self._features & SUPPORT_COLOR_TEMP: elif self._features & SUPPORT_COLOR_TEMP:
# ColorTemperature and Hue characteristic should not be # ColorTemperature and Hue characteristic should not be
# exposed both. Both states are tracked separately in HomeKit, # exposed both. Both states are tracked separately in HomeKit,
@ -179,7 +181,16 @@ class Light(HomeAccessory):
# Handle Color # Handle Color
if CHAR_SATURATION in self.chars and CHAR_HUE in self.chars: 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)): if isinstance(hue, (int, float)) and isinstance(saturation, (int, float)):
hue = round(hue, 0) hue = round(hue, 0)
saturation = round(saturation, 0) saturation = round(saturation, 0)

View file

@ -293,9 +293,25 @@ async def test_light_color_temperature_and_rgb_color(hass, hk_driver, cls, event
) )
await hass.async_block_till_done() await hass.async_block_till_done()
acc = cls.light(hass, hk_driver, "Light", entity_id, 2, None) 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") 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): async def test_light_rgb_color(hass, hk_driver, cls, events):
"""Test light with rgb_color.""" """Test light with rgb_color."""