Support color temperature in Homekit (#13658)

* Add support for color temperature
* Add test for color temp
This commit is contained in:
Niklas Morberg 2018-04-05 18:06:23 +02:00 committed by cdce8p
parent 63820a78d9
commit bb5484edac
3 changed files with 60 additions and 6 deletions

View File

@ -47,6 +47,7 @@ SERV_WINDOW_COVERING = 'WindowCovering'
# #### Characteristics ####
CHAR_BRIGHTNESS = 'Brightness' # Int | [0, 100]
CHAR_COLOR_TEMPERATURE = 'ColorTemperature'
CHAR_COOLING_THRESHOLD_TEMPERATURE = 'CoolingThresholdTemperature'
CHAR_CURRENT_HEATING_COOLING = 'CurrentHeatingCoolingState'
CHAR_CURRENT_POSITION = 'CurrentPosition'

View File

@ -2,13 +2,14 @@
import logging
from homeassistant.components.light import (
ATTR_HS_COLOR, ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, SUPPORT_COLOR)
ATTR_HS_COLOR, ATTR_COLOR_TEMP, ATTR_BRIGHTNESS, ATTR_MIN_MIREDS,
ATTR_MAX_MIREDS, SUPPORT_COLOR, SUPPORT_COLOR_TEMP, SUPPORT_BRIGHTNESS)
from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_ON, STATE_OFF
from . import TYPES
from .accessories import HomeAccessory, add_preload_service
from .const import (
CATEGORY_LIGHT, SERV_LIGHTBULB,
CATEGORY_LIGHT, SERV_LIGHTBULB, CHAR_COLOR_TEMPERATURE,
CHAR_BRIGHTNESS, CHAR_HUE, CHAR_ON, CHAR_SATURATION)
_LOGGER = logging.getLogger(__name__)
@ -20,7 +21,7 @@ RGB_COLOR = 'rgb_color'
class Light(HomeAccessory):
"""Generate a Light accessory for a light entity.
Currently supports: state, brightness, rgb_color.
Currently supports: state, brightness, color temperature, rgb_color.
"""
def __init__(self, hass, entity_id, name, **kwargs):
@ -31,7 +32,7 @@ class Light(HomeAccessory):
self.entity_id = entity_id
self._flag = {CHAR_ON: False, CHAR_BRIGHTNESS: False,
CHAR_HUE: False, CHAR_SATURATION: False,
RGB_COLOR: False}
CHAR_COLOR_TEMPERATURE: False, RGB_COLOR: False}
self._state = 0
self.chars = []
@ -39,6 +40,8 @@ class Light(HomeAccessory):
.attributes.get(ATTR_SUPPORTED_FEATURES)
if self._features & SUPPORT_BRIGHTNESS:
self.chars.append(CHAR_BRIGHTNESS)
if self._features & SUPPORT_COLOR_TEMP:
self.chars.append(CHAR_COLOR_TEMPERATURE)
if self._features & SUPPORT_COLOR:
self.chars.append(CHAR_HUE)
self.chars.append(CHAR_SATURATION)
@ -55,6 +58,18 @@ class Light(HomeAccessory):
.get_characteristic(CHAR_BRIGHTNESS)
self.char_brightness.setter_callback = self.set_brightness
self.char_brightness.value = 0
if CHAR_COLOR_TEMPERATURE in self.chars:
self.char_color_temperature = serv_light \
.get_characteristic(CHAR_COLOR_TEMPERATURE)
self.char_color_temperature.setter_callback = \
self.set_color_temperature
min_mireds = self.hass.states.get(self.entity_id) \
.attributes.get(ATTR_MIN_MIREDS, 153)
max_mireds = self.hass.states.get(self.entity_id) \
.attributes.get(ATTR_MAX_MIREDS, 500)
self.char_color_temperature.override_properties({
'minValue': min_mireds, 'maxValue': max_mireds})
self.char_color_temperature.value = min_mireds
if CHAR_HUE in self.chars:
self.char_hue = serv_light.get_characteristic(CHAR_HUE)
self.char_hue.setter_callback = self.set_hue
@ -90,6 +105,13 @@ class Light(HomeAccessory):
else:
self.hass.components.light.turn_off(self.entity_id)
def set_color_temperature(self, value):
"""Set color temperature if call came from HomeKit."""
_LOGGER.debug('%s: Set color temp to %s', self.entity_id, value)
self._flag[CHAR_COLOR_TEMPERATURE] = True
self.char_color_temperature.set_value(value, should_callback=False)
self.hass.components.light.turn_on(self.entity_id, color_temp=value)
def set_saturation(self, value):
"""Set saturation if call came from HomeKit."""
_LOGGER.debug('%s: Set saturation to %d', self.entity_id, value)
@ -141,6 +163,15 @@ class Light(HomeAccessory):
should_callback=False)
self._flag[CHAR_BRIGHTNESS] = False
# Handle color temperature
if CHAR_COLOR_TEMPERATURE in self.chars:
color_temperature = new_state.attributes.get(ATTR_COLOR_TEMP)
if not self._flag[CHAR_COLOR_TEMPERATURE] \
and isinstance(color_temperature, int):
self.char_color_temperature.set_value(color_temperature,
should_callback=False)
self._flag[CHAR_COLOR_TEMPERATURE] = False
# Handle Color
if CHAR_SATURATION in self.chars and CHAR_HUE in self.chars:
hue, saturation = new_state.attributes.get(

View File

@ -4,8 +4,8 @@ import unittest
from homeassistant.core import callback
from homeassistant.components.homekit.type_lights import Light
from homeassistant.components.light import (
DOMAIN, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_HS_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_COLOR)
DOMAIN, ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, ATTR_COLOR_TEMP,
ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_COLOR)
from homeassistant.const import (
ATTR_DOMAIN, ATTR_ENTITY_ID, ATTR_SERVICE, ATTR_SERVICE_DATA,
ATTR_SUPPORTED_FEATURES, EVENT_CALL_SERVICE, SERVICE_TURN_ON,
@ -118,6 +118,28 @@ class TestHomekitLights(unittest.TestCase):
self.assertEqual(self.events[2].data[ATTR_DOMAIN], DOMAIN)
self.assertEqual(self.events[2].data[ATTR_SERVICE], SERVICE_TURN_OFF)
def test_light_color_temperature(self):
"""Test light with color temperature."""
entity_id = 'light.demo'
self.hass.states.set(entity_id, STATE_ON, {
ATTR_SUPPORTED_FEATURES: SUPPORT_COLOR_TEMP,
ATTR_COLOR_TEMP: 190})
acc = Light(self.hass, entity_id, 'Light', aid=2)
self.assertEqual(acc.char_color_temperature.value, 153)
acc.run()
self.hass.block_till_done()
self.assertEqual(acc.char_color_temperature.value, 190)
# Set from HomeKit
acc.char_color_temperature.set_value(250)
self.hass.block_till_done()
self.assertEqual(self.events[0].data[ATTR_DOMAIN], DOMAIN)
self.assertEqual(self.events[0].data[ATTR_SERVICE], SERVICE_TURN_ON)
self.assertEqual(
self.events[0].data[ATTR_SERVICE_DATA], {
ATTR_ENTITY_ID: entity_id, ATTR_COLOR_TEMP: 250})
def test_light_rgb_color(self):
"""Test light with rgb_color."""
entity_id = 'light.demo'