2017-05-10 12:06:57 +02:00
|
|
|
"""
|
|
|
|
Support for the IKEA Tradfri platform.
|
|
|
|
|
|
|
|
For more details about this platform, please refer to the documentation at
|
|
|
|
https://home-assistant.io/components/light.tradfri/
|
|
|
|
"""
|
2017-04-18 17:26:59 +02:00
|
|
|
import logging
|
2017-04-13 19:04:42 +02:00
|
|
|
|
2017-04-16 20:35:52 +02:00
|
|
|
from homeassistant.components.light import (
|
2017-04-18 17:26:59 +02:00
|
|
|
ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS,
|
|
|
|
SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light)
|
2017-08-31 06:19:06 +02:00
|
|
|
from homeassistant.components.light import (
|
|
|
|
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA)
|
|
|
|
from homeassistant.components.tradfri import (
|
|
|
|
KEY_GATEWAY, KEY_TRADFRI_GROUPS, KEY_API)
|
2017-04-16 14:37:39 -07:00
|
|
|
from homeassistant.util import color as color_util
|
2017-04-18 17:26:59 +02:00
|
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
2017-04-13 19:04:42 +02:00
|
|
|
|
2017-04-16 14:37:39 -07:00
|
|
|
DEPENDENCIES = ['tradfri']
|
|
|
|
PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA
|
2017-04-21 23:32:51 -07:00
|
|
|
IKEA = 'IKEA of Sweden'
|
2017-08-31 06:19:06 +02:00
|
|
|
ALLOWED_TEMPERATURES = {IKEA}
|
2017-04-13 19:04:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
2017-04-30 23:10:08 -04:00
|
|
|
"""Set up the IKEA Tradfri Light platform."""
|
2017-04-16 14:37:39 -07:00
|
|
|
if discovery_info is None:
|
|
|
|
return
|
2017-04-13 19:04:42 +02:00
|
|
|
|
2017-04-16 14:37:39 -07:00
|
|
|
gateway_id = discovery_info['gateway']
|
2017-08-31 06:19:06 +02:00
|
|
|
api = hass.data[KEY_API][gateway_id]
|
2017-04-16 14:37:39 -07:00
|
|
|
gateway = hass.data[KEY_GATEWAY][gateway_id]
|
2017-08-31 06:19:06 +02:00
|
|
|
devices = api(gateway.get_devices())
|
|
|
|
lights = [dev for dev in devices if api(dev).has_light_control]
|
|
|
|
add_devices(Tradfri(light, api) for light in lights)
|
2017-04-13 19:04:42 +02:00
|
|
|
|
2017-05-17 08:26:57 +02:00
|
|
|
allow_tradfri_groups = hass.data[KEY_TRADFRI_GROUPS][gateway_id]
|
|
|
|
if allow_tradfri_groups:
|
2017-08-31 06:19:06 +02:00
|
|
|
groups = api(gateway.get_groups())
|
|
|
|
add_devices(TradfriGroup(group, api) for group in groups)
|
2017-04-25 06:57:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
class TradfriGroup(Light):
|
|
|
|
"""The platform class required by hass."""
|
|
|
|
|
2017-08-31 06:19:06 +02:00
|
|
|
def __init__(self, light, api):
|
2017-04-25 06:57:38 +02:00
|
|
|
"""Initialize a Group."""
|
2017-08-31 06:19:06 +02:00
|
|
|
self._group = api(light)
|
|
|
|
self._api = api
|
|
|
|
self._name = self._group.name
|
2017-04-25 06:57:38 +02:00
|
|
|
|
|
|
|
@property
|
|
|
|
def supported_features(self):
|
|
|
|
"""Flag supported features."""
|
|
|
|
return SUPPORT_BRIGHTNESS
|
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Return the display name of this group."""
|
|
|
|
return self._name
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_on(self):
|
|
|
|
"""Return true if group lights are on."""
|
|
|
|
return self._group.state
|
|
|
|
|
|
|
|
@property
|
|
|
|
def brightness(self):
|
2017-05-02 18:18:47 +02:00
|
|
|
"""Return the brightness of the group lights."""
|
2017-04-25 06:57:38 +02:00
|
|
|
return self._group.dimmer
|
|
|
|
|
|
|
|
def turn_off(self, **kwargs):
|
|
|
|
"""Instruct the group lights to turn off."""
|
2017-08-31 06:19:06 +02:00
|
|
|
self._api(self._group.set_state(0))
|
2017-04-25 06:57:38 +02:00
|
|
|
|
|
|
|
def turn_on(self, **kwargs):
|
|
|
|
"""Instruct the group lights to turn on, or dim."""
|
|
|
|
if ATTR_BRIGHTNESS in kwargs:
|
2017-08-31 06:19:06 +02:00
|
|
|
self._api(self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS]))
|
2017-04-25 06:57:38 +02:00
|
|
|
else:
|
2017-08-31 06:19:06 +02:00
|
|
|
self._api(self._group.set_state(1))
|
2017-04-25 06:57:38 +02:00
|
|
|
|
|
|
|
def update(self):
|
|
|
|
"""Fetch new state data for this group."""
|
2017-07-31 17:58:47 +02:00
|
|
|
from pytradfri import RequestTimeout
|
|
|
|
try:
|
2017-08-31 06:19:06 +02:00
|
|
|
self._api(self._group.update())
|
2017-07-31 17:58:47 +02:00
|
|
|
except RequestTimeout:
|
|
|
|
_LOGGER.warning("Tradfri update request timed out")
|
2017-04-25 06:57:38 +02:00
|
|
|
|
2017-04-13 19:04:42 +02:00
|
|
|
|
2017-04-16 14:37:39 -07:00
|
|
|
class Tradfri(Light):
|
2017-05-02 18:18:47 +02:00
|
|
|
"""The platform class required by Home Asisstant."""
|
2017-04-13 19:04:42 +02:00
|
|
|
|
2017-08-31 06:19:06 +02:00
|
|
|
def __init__(self, light, api):
|
2017-04-13 19:04:42 +02:00
|
|
|
"""Initialize a Light."""
|
2017-08-31 06:19:06 +02:00
|
|
|
self._light = api(light)
|
|
|
|
self._api = api
|
2017-04-13 19:04:42 +02:00
|
|
|
|
|
|
|
# Caching of LightControl and light object
|
2017-08-31 06:19:06 +02:00
|
|
|
self._light_control = self._light.light_control
|
|
|
|
self._light_data = self._light_control.lights[0]
|
|
|
|
self._name = self._light.name
|
2017-04-16 20:35:52 +02:00
|
|
|
self._rgb_color = None
|
2017-04-21 23:32:51 -07:00
|
|
|
self._features = SUPPORT_BRIGHTNESS
|
|
|
|
|
|
|
|
if self._light_data.hex_color is not None:
|
|
|
|
if self._light.device_info.manufacturer == IKEA:
|
2017-04-22 09:31:23 +02:00
|
|
|
self._features |= SUPPORT_COLOR_TEMP
|
2017-04-21 23:32:51 -07:00
|
|
|
else:
|
2017-04-22 09:31:23 +02:00
|
|
|
self._features |= SUPPORT_RGB_COLOR
|
2017-04-21 23:32:51 -07:00
|
|
|
|
2017-08-31 06:19:06 +02:00
|
|
|
self._ok_temps = \
|
|
|
|
self._light.device_info.manufacturer in ALLOWED_TEMPERATURES
|
|
|
|
|
|
|
|
@property
|
|
|
|
def min_mireds(self):
|
|
|
|
"""Return the coldest color_temp that this light supports."""
|
|
|
|
from pytradfri.color import MAX_KELVIN_WS
|
|
|
|
return color_util.color_temperature_kelvin_to_mired(MAX_KELVIN_WS)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def max_mireds(self):
|
|
|
|
"""Return the warmest color_temp that this light supports."""
|
|
|
|
from pytradfri.color import MIN_KELVIN_WS
|
|
|
|
return color_util.color_temperature_kelvin_to_mired(MIN_KELVIN_WS)
|
2017-04-13 19:04:42 +02:00
|
|
|
|
|
|
|
@property
|
|
|
|
def supported_features(self):
|
|
|
|
"""Flag supported features."""
|
2017-04-19 09:15:39 -07:00
|
|
|
return self._features
|
2017-04-13 19:04:42 +02:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Return the display name of this light."""
|
|
|
|
return self._name
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_on(self):
|
|
|
|
"""Return true if light is on."""
|
|
|
|
return self._light_data.state
|
|
|
|
|
|
|
|
@property
|
|
|
|
def brightness(self):
|
2017-05-02 18:18:47 +02:00
|
|
|
"""Return the brightness of the light."""
|
2017-04-13 19:04:42 +02:00
|
|
|
return self._light_data.dimmer
|
|
|
|
|
2017-04-18 17:26:59 +02:00
|
|
|
@property
|
|
|
|
def color_temp(self):
|
|
|
|
"""Return the CT color value in mireds."""
|
2017-08-31 06:19:06 +02:00
|
|
|
if (self._light_data.kelvin_color is None or
|
2017-04-21 23:32:51 -07:00
|
|
|
self.supported_features & SUPPORT_COLOR_TEMP == 0 or
|
|
|
|
not self._ok_temps):
|
|
|
|
return None
|
2017-08-31 06:19:06 +02:00
|
|
|
return color_util.color_temperature_kelvin_to_mired(
|
|
|
|
self._light_data.kelvin_color
|
|
|
|
)
|
2017-04-18 17:26:59 +02:00
|
|
|
|
2017-04-16 20:35:52 +02:00
|
|
|
@property
|
|
|
|
def rgb_color(self):
|
|
|
|
"""RGB color of the light."""
|
2017-04-19 09:15:39 -07:00
|
|
|
return self._rgb_color
|
2017-04-16 20:35:52 +02:00
|
|
|
|
2017-04-13 19:04:42 +02:00
|
|
|
def turn_off(self, **kwargs):
|
|
|
|
"""Instruct the light to turn off."""
|
2017-08-31 06:19:06 +02:00
|
|
|
self._api(self._light_control.set_state(False))
|
2017-04-13 19:04:42 +02:00
|
|
|
|
|
|
|
def turn_on(self, **kwargs):
|
2017-04-16 20:35:52 +02:00
|
|
|
"""
|
|
|
|
Instruct the light to turn on.
|
|
|
|
|
|
|
|
After adding "self._light_data.hexcolor is not None"
|
|
|
|
for ATTR_RGB_COLOR, this also supports Philips Hue bulbs.
|
|
|
|
"""
|
2017-04-13 19:04:42 +02:00
|
|
|
if ATTR_BRIGHTNESS in kwargs:
|
2017-08-31 06:19:06 +02:00
|
|
|
self._api(self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS]))
|
2017-04-16 14:37:39 -07:00
|
|
|
else:
|
2017-08-31 06:19:06 +02:00
|
|
|
self._api(self._light_control.set_state(True))
|
2017-04-16 14:37:39 -07:00
|
|
|
|
2017-04-16 20:35:52 +02:00
|
|
|
if ATTR_RGB_COLOR in kwargs and self._light_data.hex_color is not None:
|
full RGB support for users of tradfri GW (#9411)
* Update tradfri.py
## 201709013: set_hex_color() seems not to work in pytradfri api - set_rgb_color() does
## -> changed function set_hex_color() to set_rgb_color()
## tested w. IKEA tradfri GW and zigbee rgb PWM module (dresden elektronik FLS-PP lp)
* Update tradfri.py
Setup:
Home Assistant 0.53.0
pytradfri 2.2
IKEA tradfri gateway fw 1.1.0015
zigbee rgb PWM module (dresden elektronik FLS-PP lp)
Issue:
pytradfri's set_hex_color() does not work for arbitrary colors with the current IKEA tradfri gateway. Only setting rgb hex values (param 5706) of some predefined colors has the desired effect. Others will fall back to one predefined value. I assume, the GW doesn't allow for values deviating from the predefined values.
However, pytradfri's set_rgb_color() does also work for arbitrary colors. Latest pytradfri (2.2/PR51?) will convert rgb to xy and send xy thru the GW (param 5709 and 5710).
-> changed the function used from set_hex_color() to set_rgb_color() in HA's component\light\tradfri
Result:
Full RGB support with arbitrary colors with my setup.
Unfortunately I cannot test tradfri GW with other bulbs (no have hue/lightify bulbs).
___
Predefined colors from <https://github.com/ggravlingen/pytradfri/pull/51>:
this.f3891b = new HashMap();
this.f3891b.put("f5faf6", new C1386c(0.3804d, 0.3804d, "f5faf6", 0.54d));
this.f3891b.put("f1e0b5", new C1386c(0.4599d, 0.4106d, "CCT_LIGHT_NEUTRAL", 0.61d));
this.f3891b.put("efd275", new C1386c(0.5056d, 0.4152d, "efd275", 0.66d));
this.f3891b.put("dcf0f8", new C1386c(0.3221d, 0.3317d, "dcf0f8", 0.45d));
this.f3891b.put("eaf6fb", new C1386c(0.3451d, 0.3451d, "eaf6fb", 0.48d));
this.f3891b.put("f5faf6", new C1386c(0.3804d, 0.3804d, "f5faf6", 0.54d));
this.f3891b.put("f2eccf", new C1386c(0.4369d, 0.4041d, "f2eccf", 0.59d));
this.f3891b.put("CCT_LIGHT_NEUTRAL", new C1386c(0.4599d, 0.4106d, "CCT_LIGHT_NEUTRAL", 0.61d));
this.f3891b.put("efd275", new C1386c(0.5056d, 0.4152d, "efd275", 0.66d));
this.f3891b.put("ebb63e", new C1386c(0.5516d, 0.4075d, "ebb63e", 0.68d));
this.f3891b.put("e78834", new C1386c(0.58d, 0.38d, "e78834", 0.69d));
this.f3891b.put("e57345", new C1386c(0.58d, 0.35d, "e57345", 0.67d));
this.f3891b.put("da5d41", new C1386c(0.62d, 0.34d, "da5d41", 0.7d));
this.f3891b.put("dc4b31", new C1386c(0.66d, 0.32d, "dc4b31", 0.73d));
this.f3891b.put("e491af", new C1386c(0.5d, 0.28d, "e491af", 0.57d));
this.f3891b.put("e8bedd", new C1386c(0.45d, 0.28d, "e8bedd", 0.53d));
this.f3891b.put("d9337c", new C1386c(0.5d, 0.24d, "d9337c", 0.55d));
this.f3891b.put("c984bb", new C1386c(0.34d, 0.19d, "c984bb", 0.38d));
this.f3891b.put("8f2686", new C1386c(0.31d, 0.12d, "8f2686", 0.33d));
this.f3891b.put("4a418a", new C1386c(0.17d, 0.05d, "4a418a", 0.18d));
this.f3891b.put("6c83ba", new C1386c(0.2d, 0.1d, "6c83ba", 0.22d));
this.f3891b.put("a9d62b", new C1386c(0.4099999964237213d, 0.5099999904632568d, "a9d62b", 0.654d));
this.f3891b.put("d6e44b", new C1386c(0.44999998807907104d, 0.4699999988079071d, "d6e44b", 0.65d));
2017-09-14 07:24:46 +02:00
|
|
|
self._api(self._light.light_control.set_rgb_color(
|
|
|
|
*kwargs[ATTR_RGB_COLOR]))
|
2017-04-13 19:04:42 +02:00
|
|
|
|
2017-04-18 17:26:59 +02:00
|
|
|
elif ATTR_COLOR_TEMP in kwargs and \
|
|
|
|
self._light_data.hex_color is not None and self._ok_temps:
|
|
|
|
kelvin = color_util.color_temperature_mired_to_kelvin(
|
|
|
|
kwargs[ATTR_COLOR_TEMP])
|
2017-08-31 06:19:06 +02:00
|
|
|
self._api(self._light_control.set_kelvin_color(kelvin))
|
2017-04-18 17:26:59 +02:00
|
|
|
|
2017-04-13 19:04:42 +02:00
|
|
|
def update(self):
|
2017-04-16 20:35:52 +02:00
|
|
|
"""Fetch new state data for this light."""
|
2017-07-31 17:58:47 +02:00
|
|
|
from pytradfri import RequestTimeout
|
|
|
|
try:
|
2017-08-31 06:19:06 +02:00
|
|
|
self._api(self._light.update())
|
|
|
|
except RequestTimeout as exception:
|
|
|
|
_LOGGER.warning("Tradfri update request timed out: %s", exception)
|
2017-04-16 20:35:52 +02:00
|
|
|
|
2017-04-24 21:57:27 -07:00
|
|
|
# Handle Hue lights paired with the gateway
|
|
|
|
# hex_color is 0 when bulb is unreachable
|
|
|
|
if self._light_data.hex_color not in (None, '0'):
|
2017-04-16 20:35:52 +02:00
|
|
|
self._rgb_color = color_util.rgb_hex_to_rgb_list(
|
|
|
|
self._light_data.hex_color)
|