diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 1851579a172..ca153042f8d 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -4,11 +4,9 @@ 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/ """ -import asyncio import logging from homeassistant.core import callback -from homeassistant.const import ATTR_BATTERY_LEVEL from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_HS_COLOR, ATTR_TRANSITION, SUPPORT_BRIGHTNESS, SUPPORT_TRANSITION, SUPPORT_COLOR_TEMP, @@ -17,20 +15,19 @@ from homeassistant.components.light import \ PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA from homeassistant.components.tradfri import KEY_GATEWAY, KEY_TRADFRI_GROUPS, \ KEY_API -from homeassistant.util import color as color_util _LOGGER = logging.getLogger(__name__) +ATTR_TRANSITION_TIME = 'transition_time' DEPENDENCIES = ['tradfri'] PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA IKEA = 'IKEA of Sweden' TRADFRI_LIGHT_MANAGER = 'Tradfri Light Manager' SUPPORTED_FEATURES = (SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION) -ALLOWED_TEMPERATURES = {IKEA} -@asyncio.coroutine -def async_setup_platform(hass, config, async_add_devices, discovery_info=None): +async def async_setup_platform(hass, config, + async_add_devices, discovery_info=None): """Set up the IKEA Tradfri Light platform.""" if discovery_info is None: return @@ -40,8 +37,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): gateway = hass.data[KEY_GATEWAY][gateway_id] devices_command = gateway.get_devices() - devices_commands = yield from api(devices_command) - devices = yield from api(devices_commands) + devices_commands = await api(devices_command) + devices = await api(devices_commands) lights = [dev for dev in devices if dev.has_light_control] if lights: async_add_devices(TradfriLight(light, api) for light in lights) @@ -49,8 +46,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): allow_tradfri_groups = hass.data[KEY_TRADFRI_GROUPS][gateway_id] if allow_tradfri_groups: groups_command = gateway.get_groups() - groups_commands = yield from api(groups_command) - groups = yield from api(groups_commands) + groups_commands = await api(groups_command) + groups = await api(groups_commands) if groups: async_add_devices(TradfriGroup(group, api) for group in groups) @@ -66,8 +63,7 @@ class TradfriGroup(Light): self._refresh(light) - @asyncio.coroutine - def async_added_to_hass(self): + async def async_added_to_hass(self): """Start thread when added to hass.""" self._async_start_observe() @@ -96,13 +92,11 @@ class TradfriGroup(Light): """Return the brightness of the group lights.""" return self._group.dimmer - @asyncio.coroutine - def async_turn_off(self, **kwargs): + async def async_turn_off(self, **kwargs): """Instruct the group lights to turn off.""" - yield from self._api(self._group.set_state(0)) + await self._api(self._group.set_state(0)) - @asyncio.coroutine - def async_turn_on(self, **kwargs): + async def async_turn_on(self, **kwargs): """Instruct the group lights to turn on, or dim.""" keys = {} if ATTR_TRANSITION in kwargs: @@ -112,16 +106,16 @@ class TradfriGroup(Light): if kwargs[ATTR_BRIGHTNESS] == 255: kwargs[ATTR_BRIGHTNESS] = 254 - yield from self._api( + await self._api( self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS], **keys)) else: - yield from self._api(self._group.set_state(1)) + await self._api(self._group.set_state(1)) @callback def _async_start_observe(self, exc=None): """Start observation of light.""" # pylint: disable=import-error - from pytradfri.error import PyTradFriError + from pytradfri.error import PytradfriError if exc: _LOGGER.warning("Observation failed for %s", self._name, exc_info=exc) @@ -131,7 +125,7 @@ class TradfriGroup(Light): err_callback=self._async_start_observe, duration=0) self.hass.async_add_job(self._api(cmd)) - except PyTradFriError as err: + except PytradfriError as err: _LOGGER.warning("Observation failed, trying again", exc_info=err) self._async_start_observe() @@ -159,7 +153,6 @@ class TradfriLight(Light): self._name = None self._hs_color = None self._features = SUPPORTED_FEATURES - self._temp_supported = False self._available = True self._refresh(light) @@ -167,33 +160,14 @@ class TradfriLight(Light): @property def min_mireds(self): """Return the coldest color_temp that this light supports.""" - if self._light_control.max_kelvin is not None: - return color_util.color_temperature_kelvin_to_mired( - self._light_control.max_kelvin - ) + return self._light_control.min_mireds @property def max_mireds(self): """Return the warmest color_temp that this light supports.""" - if self._light_control.min_kelvin is not None: - return color_util.color_temperature_kelvin_to_mired( - self._light_control.min_kelvin - ) + return self._light_control.max_mireds - @property - def device_state_attributes(self): - """Return the devices' state attributes.""" - info = self._light.device_info - - attrs = {} - - if info.battery_level is not None: - attrs[ATTR_BATTERY_LEVEL] = info.battery_level - - return attrs - - @asyncio.coroutine - def async_added_to_hass(self): + async def async_added_to_hass(self): """Start thread when added to hass.""" self._async_start_observe() @@ -229,64 +203,73 @@ class TradfriLight(Light): @property def color_temp(self): - """Return the CT color value in mireds.""" - kelvin_color = self._light_data.kelvin_color_inferred - if kelvin_color is not None: - return color_util.color_temperature_kelvin_to_mired( - kelvin_color - ) + """Return the color temp value in mireds.""" + return self._light_data.color_temp @property def hs_color(self): """HS color of the light.""" - return self._hs_color + if self._light_control.can_set_color: + hsbxy = self._light_data.hsb_xy_color + hue = hsbxy[0] / (65535 / 360) + sat = hsbxy[1] / (65279 / 100) + if hue is not None and sat is not None: + return hue, sat - @asyncio.coroutine - def async_turn_off(self, **kwargs): + async def async_turn_off(self, **kwargs): """Instruct the light to turn off.""" - yield from self._api(self._light_control.set_state(False)) + await self._api(self._light_control.set_state(False)) - @asyncio.coroutine - def async_turn_on(self, **kwargs): - """ - Instruct the light to turn on. - - After adding "self._light_data.hexcolor is not None" - for ATTR_HS_COLOR, this also supports Philips Hue bulbs. - """ - if ATTR_HS_COLOR in kwargs and self._light_data.hex_color is not None: - rgb = color_util.color_hs_to_RGB(*kwargs[ATTR_HS_COLOR]) - yield from self._api( - self._light.light_control.set_rgb_color(*rgb)) - - elif ATTR_COLOR_TEMP in kwargs and \ - self._light_data.hex_color is not None and \ - self._temp_supported: - kelvin = color_util.color_temperature_mired_to_kelvin( - kwargs[ATTR_COLOR_TEMP]) - yield from self._api( - self._light_control.set_kelvin_color(kelvin)) - - keys = {} + async def async_turn_on(self, **kwargs): + """Instruct the light to turn on.""" + params = {} + transition_time = None if ATTR_TRANSITION in kwargs: - keys['transition_time'] = int(kwargs[ATTR_TRANSITION]) * 10 + transition_time = int(kwargs[ATTR_TRANSITION]) * 10 - if ATTR_BRIGHTNESS in kwargs: - if kwargs[ATTR_BRIGHTNESS] == 255: - kwargs[ATTR_BRIGHTNESS] = 254 + brightness = kwargs.get(ATTR_BRIGHTNESS) - yield from self._api( - self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS], - **keys)) + if brightness is not None: + if brightness > 254: + brightness = 254 + elif brightness < 0: + brightness = 0 + + if ATTR_HS_COLOR in kwargs and self._light_control.can_set_color: + params[ATTR_BRIGHTNESS] = brightness + hue = int(kwargs[ATTR_HS_COLOR][0] * (65535 / 360)) + sat = int(kwargs[ATTR_HS_COLOR][1] * (65279 / 100)) + await self._api( + self._light_control.set_hsb(hue, sat, **params)) + return + + if ATTR_COLOR_TEMP in kwargs and self._light_control.can_set_temp: + temp = kwargs[ATTR_COLOR_TEMP] + if temp > self.max_mireds: + temp = self.max_mireds + elif temp < self.min_mireds: + temp = self.min_mireds + + if brightness is None: + params[ATTR_TRANSITION_TIME] = transition_time + await self._api( + self._light_control.set_color_temp(temp, + **params)) + + if brightness is not None: + params[ATTR_TRANSITION_TIME] = transition_time + await self._api( + self._light_control.set_dimmer(brightness, + **params)) else: - yield from self._api( + await self._api( self._light_control.set_state(True)) @callback def _async_start_observe(self, exc=None): """Start observation of light.""" # pylint: disable=import-error - from pytradfri.error import PyTradFriError + from pytradfri.error import PytradfriError if exc: _LOGGER.warning("Observation failed for %s", self._name, exc_info=exc) @@ -296,7 +279,7 @@ class TradfriLight(Light): err_callback=self._async_start_observe, duration=0) self.hass.async_add_job(self._api(cmd)) - except PyTradFriError as err: + except PytradfriError as err: _LOGGER.warning("Observation failed, trying again", exc_info=err) self._async_start_observe() @@ -309,27 +292,15 @@ class TradfriLight(Light): self._light_control = light.light_control self._light_data = light.light_control.lights[0] self._name = light.name - self._hs_color = None self._features = SUPPORTED_FEATURES - if self._light.device_info.manufacturer == IKEA: - if self._light_control.can_set_kelvin: - self._features |= SUPPORT_COLOR_TEMP - if self._light_control.can_set_color: - self._features |= SUPPORT_COLOR - else: - if self._light_data.hex_color is not None: - self._features |= SUPPORT_COLOR - - self._temp_supported = self._light.device_info.manufacturer \ - in ALLOWED_TEMPERATURES + if light.light_control.can_set_color: + self._features |= SUPPORT_COLOR + if light.light_control.can_set_temp: + self._features |= SUPPORT_COLOR_TEMP @callback def _observe_update(self, tradfri_device): """Receive new state data for this light.""" self._refresh(tradfri_device) - rgb = color_util.rgb_hex_to_rgb_list( - self._light_data.hex_color_inferred - ) - self._hs_color = color_util.color_RGB_to_hs(*rgb) self.async_schedule_update_ha_state() diff --git a/homeassistant/components/sensor/tradfri.py b/homeassistant/components/sensor/tradfri.py index d087fdda9f6..df931770cf2 100644 --- a/homeassistant/components/sensor/tradfri.py +++ b/homeassistant/components/sensor/tradfri.py @@ -4,7 +4,6 @@ Support for the IKEA Tradfri platform. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.tradfri/ """ -import asyncio import logging from datetime import timedelta @@ -20,8 +19,8 @@ DEPENDENCIES = ['tradfri'] SCAN_INTERVAL = timedelta(minutes=5) -@asyncio.coroutine -def async_setup_platform(hass, config, async_add_devices, discovery_info=None): +async def async_setup_platform(hass, config, async_add_devices, + discovery_info=None): """Set up the IKEA Tradfri device platform.""" if discovery_info is None: return @@ -31,8 +30,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): gateway = hass.data[KEY_GATEWAY][gateway_id] devices_command = gateway.get_devices() - devices_commands = yield from api(devices_command) - all_devices = yield from api(devices_commands) + devices_commands = await api(devices_command) + all_devices = await api(devices_commands) devices = [dev for dev in all_devices if not dev.has_light_control] async_add_devices(TradfriDevice(device, api) for device in devices) @@ -48,8 +47,7 @@ class TradfriDevice(Entity): self._refresh(device) - @asyncio.coroutine - def async_added_to_hass(self): + async def async_added_to_hass(self): """Start thread when added to hass.""" self._async_start_observe() @@ -91,7 +89,7 @@ class TradfriDevice(Entity): def _async_start_observe(self, exc=None): """Start observation of light.""" # pylint: disable=import-error - from pytradfri.error import PyTradFriError + from pytradfri.error import PytradfriError if exc: _LOGGER.warning("Observation failed for %s", self._name, exc_info=exc) @@ -101,7 +99,7 @@ class TradfriDevice(Entity): err_callback=self._async_start_observe, duration=0) self.hass.async_add_job(self._api(cmd)) - except PyTradFriError as err: + except PytradfriError as err: _LOGGER.warning("Observation failed, trying again", exc_info=err) self._async_start_observe() diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 5ac4d2a4eb1..72d1b4c769f 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -1,10 +1,9 @@ """ -Support for Ikea Tradfri. +Support for IKEA Tradfri. For more details about this component, please refer to the documentation at https://home-assistant.io/components/ikea_tradfri/ """ -import asyncio import logging from uuid import uuid4 @@ -16,7 +15,7 @@ from homeassistant.const import CONF_HOST from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI from homeassistant.util.json import load_json, save_json -REQUIREMENTS = ['pytradfri[async]==4.1.0'] +REQUIREMENTS = ['pytradfri[async]==5.4.2'] DOMAIN = 'tradfri' GATEWAY_IDENTITY = 'homeassistant' @@ -49,8 +48,7 @@ def request_configuration(hass, config, host): if instance: return - @asyncio.coroutine - def configuration_callback(callback_data): + async def configuration_callback(callback_data): """Handle the submitted configuration.""" try: from pytradfri.api.aiocoap_api import APIFactory @@ -67,14 +65,14 @@ def request_configuration(hass, config, host): # pytradfri aiocoap API into an endless loop. # Should just raise a requestError or something. try: - key = yield from api_factory.generate_psk(security_code) + key = await api_factory.generate_psk(security_code) except RequestError: configurator.async_notify_errors(hass, instance, "Security Code not accepted.") return - res = yield from _setup_gateway(hass, config, host, identity, key, - DEFAULT_ALLOW_TRADFRI_GROUPS) + res = await _setup_gateway(hass, config, host, identity, key, + DEFAULT_ALLOW_TRADFRI_GROUPS) if not res: configurator.async_notify_errors(hass, instance, @@ -101,18 +99,16 @@ def request_configuration(hass, config, host): ) -@asyncio.coroutine -def async_setup(hass, config): +async def async_setup(hass, config): """Set up the Tradfri component.""" conf = config.get(DOMAIN, {}) host = conf.get(CONF_HOST) allow_tradfri_groups = conf.get(CONF_ALLOW_TRADFRI_GROUPS) - known_hosts = yield from hass.async_add_job(load_json, - hass.config.path(CONFIG_FILE)) + known_hosts = await hass.async_add_job(load_json, + hass.config.path(CONFIG_FILE)) - @asyncio.coroutine - def gateway_discovered(service, info, - allow_tradfri_groups=DEFAULT_ALLOW_TRADFRI_GROUPS): + async def gateway_discovered(service, info, + allow_groups=DEFAULT_ALLOW_TRADFRI_GROUPS): """Run when a gateway is discovered.""" host = info['host'] @@ -121,23 +117,22 @@ def async_setup(hass, config): # identity was hard coded as 'homeassistant' identity = known_hosts[host].get('identity', 'homeassistant') key = known_hosts[host].get('key') - yield from _setup_gateway(hass, config, host, identity, key, - allow_tradfri_groups) + await _setup_gateway(hass, config, host, identity, key, + allow_groups) else: hass.async_add_job(request_configuration, hass, config, host) discovery.async_listen(hass, SERVICE_IKEA_TRADFRI, gateway_discovered) if host: - yield from gateway_discovered(None, - {'host': host}, - allow_tradfri_groups) + await gateway_discovered(None, + {'host': host}, + allow_tradfri_groups) return True -@asyncio.coroutine -def _setup_gateway(hass, hass_config, host, identity, key, - allow_tradfri_groups): +async def _setup_gateway(hass, hass_config, host, identity, key, + allow_tradfri_groups): """Create a gateway.""" from pytradfri import Gateway, RequestError # pylint: disable=import-error try: @@ -151,7 +146,7 @@ def _setup_gateway(hass, hass_config, host, identity, key, loop=hass.loop) api = factory.request gateway = Gateway() - gateway_info_result = yield from api(gateway.get_gateway_info()) + gateway_info_result = await api(gateway.get_gateway_info()) except RequestError: _LOGGER.exception("Tradfri setup failed.") return False diff --git a/requirements_all.txt b/requirements_all.txt index 10e6050bd4b..15f6c1ddbda 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1021,7 +1021,7 @@ pytouchline==0.7 pytrackr==0.0.5 # homeassistant.components.tradfri -pytradfri[async]==4.1.0 +pytradfri[async]==5.4.2 # homeassistant.components.device_tracker.unifi pyunifi==2.13