From fb921f3d1060bd8b317606cab18fae553c3db2ff Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Mon, 29 May 2017 17:55:00 +0100 Subject: [PATCH 01/43] [light.tradfri] Initial support for observe --- homeassistant/components/light/tradfri.py | 81 +++++++++++++++++------ homeassistant/components/tradfri.py | 3 +- requirements_all.txt | 6 +- 3 files changed, 67 insertions(+), 23 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 28c42c5699c778..4328cf1ea26cb3 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -4,7 +4,10 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/light.tradfri/ """ +import asyncio import logging +import threading +import time from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, @@ -19,6 +22,7 @@ DEPENDENCIES = ['tradfri'] PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA IKEA = 'IKEA of Sweden' +TRADFRI_LIGHT_MANAGER = 'Tradfri Light Manager' ALLOWED_TEMPERATURES = { IKEA: {2200: 'efd275', 2700: 'f1e0b5', 4000: 'f5faf6'} } @@ -31,9 +35,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): gateway_id = discovery_info['gateway'] gateway = hass.data[KEY_GATEWAY][gateway_id] + devices = gateway.get_devices() lights = [dev for dev in devices if dev.has_light_control] - add_devices(Tradfri(light) for light in lights) + add_devices(TradfriLight(light) for light in lights) allow_tradfri_groups = hass.data[KEY_TRADFRI_GROUPS][gateway_id] if allow_tradfri_groups: @@ -85,28 +90,33 @@ def update(self): self._group.update() -class Tradfri(Light): +class TradfriLight(Light): """The platform class required by Home Asisstant.""" def __init__(self, light): """Initialize a Light.""" - self._light = light - - # Caching of LightControl and light object - self._light_control = light.light_control - self._light_data = light.light_control.lights[0] - self._name = light.name + self._light = None + self._light_control = None + self._light_data = None + self._name = None self._rgb_color = None - self._features = SUPPORT_BRIGHTNESS + self._features = None + self._ok_temps = None + self._thread = None - if self._light_data.hex_color is not None: - if self._light.device_info.manufacturer == IKEA: - self._features |= SUPPORT_COLOR_TEMP - else: - self._features |= SUPPORT_RGB_COLOR + self._refresh(light) - self._ok_temps = ALLOWED_TEMPERATURES.get( - self._light.device_info.manufacturer) + @asyncio.coroutine + def async_added_to_hass(self): + """Start thread when added to hass.""" + self._thread = threading.Thread(target=self._start_observe) + self._thread.daemon = True + self._thread.start() + + @property + def should_poll(self): + """No polling needed for tradfri light.""" + return False @property def supported_features(self): @@ -179,12 +189,45 @@ def turn_on(self, **kwargs): kelvin = min(self._ok_temps.keys(), key=lambda x: abs(x - kelvin)) self._light_control.set_hex_color(self._ok_temps[kelvin]) - def update(self): - """Fetch new state data for this light.""" - self._light.update() + def _start_observe(self): + """Start observation of light.""" + from pytradfri.error import RequestError + + while True: + try: + self._light.observe(callback=self._observe_update, duration=-1) + except RequestError: + time.sleep(5) + _LOGGER.debug("Reconnecting observe for %s", self.name) + + def _refresh(self, light): + """Refresh the light data.""" + self._light = light + + # Caching of LightControl and light object + self._light_control = light.light_control + self._light_data = light.light_control.lights[0] + self._name = light.name + self._rgb_color = None + self._features = SUPPORT_BRIGHTNESS + + if self._light_data.hex_color is not None: + if self._light.device_info.manufacturer == IKEA: + self._features |= SUPPORT_COLOR_TEMP + else: + self._features |= SUPPORT_RGB_COLOR + + self._ok_temps = ALLOWED_TEMPERATURES.get( + self._light.device_info.manufacturer) + + def _observe_update(self, tradfri_device): + """Receive new state data for this light.""" + self._refresh(tradfri_device) # 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'): self._rgb_color = color_util.rgb_hex_to_rgb_list( self._light_data.hex_color) + + self.schedule_update_ha_state() diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index cd83f81afd1177..8e662b79bb6f2e 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -17,7 +17,8 @@ from homeassistant.loader import get_component from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI -REQUIREMENTS = ['pytradfri==1.1'] +REQUIREMENTS = ['https://github.com/ggravlingen/pytradfri/archive/' + 'c7f7e4ca1bbc147d6351fea7694fa9583e56ef54.zip#pytradfri==1.1'] DOMAIN = 'tradfri' CONFIG_FILE = 'tradfri.conf' diff --git a/requirements_all.txt b/requirements_all.txt index 47a3a4c7fb19c8..010a7112bf8eaf 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -276,6 +276,9 @@ https://github.com/aparraga/braviarc/archive/0.3.7.zip#braviarc==0.3.7 # homeassistant.components.cover.myq https://github.com/arraylabs/pymyq/archive/v0.0.8.zip#pymyq==0.0.8 +# homeassistant.components.tradfri +https://github.com/ggravlingen/pytradfri/archive/c7f7e4ca1bbc147d6351fea7694fa9583e56ef54.zip#pytradfri==1.1 + # homeassistant.components.media_player.spotify https://github.com/happyleavesaoc/spotipy/archive/544614f4b1d508201d363e84e871f86c90aa26b2.zip#spotipy==2.4.4 @@ -704,9 +707,6 @@ python_openzwave==0.4.0.31 # homeassistant.components.device_tracker.trackr pytrackr==0.0.5 -# homeassistant.components.tradfri -pytradfri==1.1 - # homeassistant.components.device_tracker.unifi pyunifi==2.12 From 416559b5abacbce8de268c7bd5e45f65f99f6790 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Mon, 5 Jun 2017 20:54:19 +0100 Subject: [PATCH 02/43] Update for pytradfri 2.0 --- homeassistant/components/light/tradfri.py | 127 +++++++++++++++------- homeassistant/components/tradfri.py | 11 +- requirements_all.txt | 2 +- 3 files changed, 97 insertions(+), 43 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 4328cf1ea26cb3..45e995aa2f276b 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -6,15 +6,20 @@ """ import asyncio import logging -import threading import time +try: + from asyncio import ensure_future +except ImportError: + from asyncio import async as ensure_future + from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light) from homeassistant.components.light import \ PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA -from homeassistant.components.tradfri import KEY_GATEWAY, KEY_TRADFRI_GROUPS +from homeassistant.components.tradfri import KEY_GATEWAY, KEY_TRADFRI_GROUPS, \ + KEY_API from homeassistant.util import color as color_util _LOGGER = logging.getLogger(__name__) @@ -28,32 +33,52 @@ } -def setup_platform(hass, config, add_devices, discovery_info=None): +@asyncio.coroutine +def async_setup_platform(hass, config, add_devices, discovery_info=None): """Set up the IKEA Tradfri Light platform.""" if discovery_info is None: return gateway_id = discovery_info['gateway'] gateway = hass.data[KEY_GATEWAY][gateway_id] + api = hass.data[KEY_API] - devices = gateway.get_devices() + devices_command = gateway.get_devices() + devices_commands = yield from api(devices_command) + devices = yield from api(*devices_commands) lights = [dev for dev in devices if dev.has_light_control] - add_devices(TradfriLight(light) for light in lights) + yield from add_devices(TradfriLight(light, api, hass) for light in lights) allow_tradfri_groups = hass.data[KEY_TRADFRI_GROUPS][gateway_id] if allow_tradfri_groups: - groups = gateway.get_groups() - add_devices(TradfriGroup(group) for group in groups) + groups_command = gateway.get_groups() + groups_commands = yield from api(groups_command) + groups = yield from api(*groups_commands) + yield from add_devices(TradfriGroup(group, api, hass) for group in groups) class TradfriGroup(Light): """The platform class required by hass.""" - def __init__(self, light): + def __init__(self, light, api, hass): """Initialize a Group.""" + self._hass = hass + self._api = api self._group = light self._name = light.name + self._refresh(light) + + @asyncio.coroutine + def async_added_to_hass(self): + """Start thread when added to hass.""" + self._start_observe() + + @property + def should_poll(self): + """No polling needed for tradfri group.""" + return False + @property def supported_features(self): """Flag supported features.""" @@ -74,27 +99,51 @@ def brightness(self): """Return the brightness of the group lights.""" return self._group.dimmer - def turn_off(self, **kwargs): + @asyncio.coroutine + def async_turn_off(self, **kwargs): """Instruct the group lights to turn off.""" - return self._group.set_state(0) + result = yield from self._api(self._group.set_state(0)) + return result - def turn_on(self, **kwargs): + @asyncio.coroutine + def async_turn_on(self, **kwargs): """Instruct the group lights to turn on, or dim.""" if ATTR_BRIGHTNESS in kwargs: - self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS]) + yield from self._api( + self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS])) else: - self._group.set_state(1) + yield from self._api(self._group.set_state(1)) - def update(self): - """Fetch new state data for this group.""" - self._group.update() + def _start_observe(self, err=None): + """Start observation of light.""" + if err: + _LOGGER.info("Observation failed for {}".format(self._name), err) + + observe_command = self._group.observe(callback=self._observe_update, + err_callback=self._start_observe, + duration=0) + observe_task = self._api(observe_command) + ensure_future(observe_task, loop=self._hass.loop) + + def _refresh(self, group): + """Refresh the light data.""" + self._group = group + self._name = group.name + + def _observe_update(self, tradfri_device): + """Receive new state data for this light.""" + self._refresh(tradfri_device) + + self.schedule_update_ha_state() class TradfriLight(Light): """The platform class required by Home Asisstant.""" - def __init__(self, light): + def __init__(self, light, api, hass): """Initialize a Light.""" + self._hass = hass + self._api = api self._light = None self._light_control = None self._light_data = None @@ -102,16 +151,13 @@ def __init__(self, light): self._rgb_color = None self._features = None self._ok_temps = None - self._thread = None self._refresh(light) @asyncio.coroutine def async_added_to_hass(self): """Start thread when added to hass.""" - self._thread = threading.Thread(target=self._start_observe) - self._thread.daemon = True - self._thread.start() + self._start_observe() @property def should_poll(self): @@ -161,11 +207,14 @@ def rgb_color(self): """RGB color of the light.""" return self._rgb_color - def turn_off(self, **kwargs): + @asyncio.coroutine + def async_turn_off(self, **kwargs): """Instruct the light to turn off.""" - return self._light_control.set_state(False) + result = yield from self._api(self._light_control.set_state(False)) + return result - def turn_on(self, **kwargs): + @asyncio.coroutine + def async_turn_on(self, **kwargs): """ Instruct the light to turn on. @@ -173,13 +222,14 @@ def turn_on(self, **kwargs): for ATTR_RGB_COLOR, this also supports Philips Hue bulbs. """ if ATTR_BRIGHTNESS in kwargs: - self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS]) + yield from self._api( + self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS])) else: - self._light_control.set_state(True) + yield from self._api(self._light_control.set_state(True)) if ATTR_RGB_COLOR in kwargs and self._light_data.hex_color is not None: - self._light.light_control.set_hex_color( - color_util.color_rgb_to_hex(*kwargs[ATTR_RGB_COLOR])) + yield from self._api(self._light.light_control.set_hex_color( + color_util.color_rgb_to_hex(*kwargs[ATTR_RGB_COLOR]))) elif ATTR_COLOR_TEMP in kwargs and \ self._light_data.hex_color is not None and self._ok_temps: @@ -187,18 +237,19 @@ def turn_on(self, **kwargs): kwargs[ATTR_COLOR_TEMP]) # find closest allowed kelvin temp from user input kelvin = min(self._ok_temps.keys(), key=lambda x: abs(x - kelvin)) - self._light_control.set_hex_color(self._ok_temps[kelvin]) + yield from self._api( + self._light_control.set_hex_color(self._ok_temps[kelvin])) - def _start_observe(self): + def _start_observe(self, err=None): """Start observation of light.""" - from pytradfri.error import RequestError - - while True: - try: - self._light.observe(callback=self._observe_update, duration=-1) - except RequestError: - time.sleep(5) - _LOGGER.debug("Reconnecting observe for %s", self.name) + if err: + _LOGGER.info("Observation failed for {}".format(self._name), err) + + observe_command = self._light.observe(callback=self._observe_update, + err_callback=self._start_observe, + duration=0) + observe_task = self._api(observe_command) + ensure_future(observe_task, loop=self._hass.loop) def _refresh(self, light): """Refresh the light data.""" diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 8e662b79bb6f2e..706faf62dbcc52 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -18,13 +18,14 @@ from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI REQUIREMENTS = ['https://github.com/ggravlingen/pytradfri/archive/' - 'c7f7e4ca1bbc147d6351fea7694fa9583e56ef54.zip#pytradfri==1.1'] + 'f90bef758079b6e3cd86dc77e329aba22161ca69.zip#pytradfri==2.0'] DOMAIN = 'tradfri' CONFIG_FILE = 'tradfri.conf' KEY_CONFIG = 'tradfri_configuring' KEY_GATEWAY = 'tradfri_gateway' KEY_TRADFRI_GROUPS = 'tradfri_allow_tradfri_groups' +KEY_API = 'tradfri_api' CONF_ALLOW_TRADFRI_GROUPS = 'allow_tradfri_groups' DEFAULT_ALLOW_TRADFRI_GROUPS = True @@ -111,14 +112,16 @@ def gateway_discovered(service, info): @asyncio.coroutine def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): """Create a gateway.""" - from pytradfri import cli_api_factory, Gateway, RequestError, retry_timeout + from pytradfri import Gateway, RequestError + from pytradfri.api.aiocoap_api import api_factory try: - api = retry_timeout(cli_api_factory(host, key)) + api = yield from api_factory(host, key) + hass.data[KEY_API] = api except RequestError: return False - gateway = Gateway(api) + gateway = Gateway() gateway_id = gateway.get_gateway_info().id hass.data.setdefault(KEY_GATEWAY, {}) gateways = hass.data[KEY_GATEWAY] diff --git a/requirements_all.txt b/requirements_all.txt index ab311fcef653f1..7bd8fb08981d02 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -277,7 +277,7 @@ https://github.com/LinuxChristian/pyW215/archive/v0.4.zip#pyW215==0.4 https://github.com/aparraga/braviarc/archive/0.3.7.zip#braviarc==0.3.7 # homeassistant.components.tradfri -https://github.com/ggravlingen/pytradfri/archive/c7f7e4ca1bbc147d6351fea7694fa9583e56ef54.zip#pytradfri==1.1 +https://github.com/ggravlingen/pytradfri/archive/f90bef758079b6e3cd86dc77e329aba22161ca69.zip#pytradfri==2.0 # homeassistant.components.media_player.spotify https://github.com/happyleavesaoc/spotipy/archive/544614f4b1d508201d363e84e871f86c90aa26b2.zip#spotipy==2.4.4 From 976527ca1c31044f64345639d8a9028f596dab06 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Mon, 5 Jun 2017 21:15:38 +0100 Subject: [PATCH 03/43] Fix imports --- homeassistant/components/light/tradfri.py | 4 ++-- homeassistant/components/tradfri.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 45e995aa2f276b..72f0716289629a 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -6,7 +6,6 @@ """ import asyncio import logging -import time try: from asyncio import ensure_future @@ -54,7 +53,8 @@ def async_setup_platform(hass, config, add_devices, discovery_info=None): groups_command = gateway.get_groups() groups_commands = yield from api(groups_command) groups = yield from api(*groups_commands) - yield from add_devices(TradfriGroup(group, api, hass) for group in groups) + yield from add_devices(TradfriGroup(group, api, hass) + for group in groups) class TradfriGroup(Light): diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 706faf62dbcc52..502ae7c15784b5 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -112,7 +112,8 @@ def gateway_discovered(service, info): @asyncio.coroutine def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): """Create a gateway.""" - from pytradfri import Gateway, RequestError + from pytradfri.error import RequestError + from pytradfri.gateway import Gateway from pytradfri.api.aiocoap_api import api_factory try: From ebc408a61f25d4b0dcc71e6a708f051ef7fedf15 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Mon, 5 Jun 2017 21:38:31 +0100 Subject: [PATCH 04/43] Fix missing call --- homeassistant/components/tradfri.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 502ae7c15784b5..94dfcd095eb9f2 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -123,7 +123,9 @@ def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): return False gateway = Gateway() - gateway_id = gateway.get_gateway_info().id + gateway_id_cmd = gateway.get_gateway_info() + gateway_id_result = yield from api(gateway_id_cmd) + gateway_id = gateway_id_result.id hass.data.setdefault(KEY_GATEWAY, {}) gateways = hass.data[KEY_GATEWAY] From 304857fb746c7ca75b60b840f368d4532d2fbbcc Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Mon, 5 Jun 2017 21:43:51 +0100 Subject: [PATCH 05/43] Don't yield from add devices --- homeassistant/components/light/tradfri.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 72f0716289629a..927db0899f8a16 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -46,15 +46,14 @@ def async_setup_platform(hass, config, add_devices, discovery_info=None): devices_commands = yield from api(devices_command) devices = yield from api(*devices_commands) lights = [dev for dev in devices if dev.has_light_control] - yield from add_devices(TradfriLight(light, api, hass) for light in lights) + add_devices(TradfriLight(light, api, hass) for light in lights) 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) - yield from add_devices(TradfriGroup(group, api, hass) - for group in groups) + add_devices(TradfriGroup(group, api, hass) for group in groups) class TradfriGroup(Light): From 264b43cd33473213f53de947dac84d9acc9e488e Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Mon, 5 Jun 2017 21:50:36 +0100 Subject: [PATCH 06/43] Fix imports --- homeassistant/components/tradfri.py | 5 ++--- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 94dfcd095eb9f2..a64d1607dcba77 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -18,7 +18,7 @@ from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI REQUIREMENTS = ['https://github.com/ggravlingen/pytradfri/archive/' - 'f90bef758079b6e3cd86dc77e329aba22161ca69.zip#pytradfri==2.0'] + '39da698c225dce712bf14e3edd9d8fdfd10153f1.zip#pytradfri==2.0'] DOMAIN = 'tradfri' CONFIG_FILE = 'tradfri.conf' @@ -112,8 +112,7 @@ def gateway_discovered(service, info): @asyncio.coroutine def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): """Create a gateway.""" - from pytradfri.error import RequestError - from pytradfri.gateway import Gateway + from pytradfri import Gateway, RequestError from pytradfri.api.aiocoap_api import api_factory try: diff --git a/requirements_all.txt b/requirements_all.txt index 7bd8fb08981d02..ec724264154016 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -277,7 +277,7 @@ https://github.com/LinuxChristian/pyW215/archive/v0.4.zip#pyW215==0.4 https://github.com/aparraga/braviarc/archive/0.3.7.zip#braviarc==0.3.7 # homeassistant.components.tradfri -https://github.com/ggravlingen/pytradfri/archive/f90bef758079b6e3cd86dc77e329aba22161ca69.zip#pytradfri==2.0 +https://github.com/ggravlingen/pytradfri/archive/39da698c225dce712bf14e3edd9d8fdfd10153f1.zip#pytradfri==2.0 # homeassistant.components.media_player.spotify https://github.com/happyleavesaoc/spotipy/archive/544614f4b1d508201d363e84e871f86c90aa26b2.zip#spotipy==2.4.4 From b83ce622187d8ba9203f621d8e488457b4451761 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Tue, 6 Jun 2017 06:43:54 +0100 Subject: [PATCH 07/43] Minor fixes to async code. --- homeassistant/components/light/tradfri.py | 62 +++++++++++++---------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 927db0899f8a16..6a9204bc0881b9 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -7,6 +7,8 @@ import asyncio import logging +from homeassistant.core import callback + try: from asyncio import ensure_future except ImportError: @@ -46,32 +48,31 @@ def async_setup_platform(hass, config, add_devices, discovery_info=None): devices_commands = yield from api(devices_command) devices = yield from api(*devices_commands) lights = [dev for dev in devices if dev.has_light_control] - add_devices(TradfriLight(light, api, hass) for light in lights) + add_devices(TradfriLight(light, api) for light in lights) 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) - add_devices(TradfriGroup(group, api, hass) for group in groups) + add_devices(TradfriGroup(group, api) for group in groups) class TradfriGroup(Light): """The platform class required by hass.""" - def __init__(self, light, api, hass): + def __init__(self, light, api): """Initialize a Group.""" - self._hass = hass self._api = api self._group = light self._name = light.name - self._refresh(light) + self._async_refresh(light) @asyncio.coroutine def async_added_to_hass(self): """Start thread when added to hass.""" - self._start_observe() + self._async_start_observe() @property def should_poll(self): @@ -113,35 +114,39 @@ def async_turn_on(self, **kwargs): else: yield from self._api(self._group.set_state(1)) - def _start_observe(self, err=None): + @callback + def _async_start_observe(self, err=None): """Start observation of light.""" if err: _LOGGER.info("Observation failed for {}".format(self._name), err) - observe_command = self._group.observe(callback=self._observe_update, - err_callback=self._start_observe, + observe_command = self._group.observe(callback= + self._async_observe_update, + err_callback= + self._async_start_observe, duration=0) observe_task = self._api(observe_command) - ensure_future(observe_task, loop=self._hass.loop) + self.hass.async_add_job(observe_task) - def _refresh(self, group): + @callback + def _async_refresh(self, group): """Refresh the light data.""" self._group = group self._name = group.name - def _observe_update(self, tradfri_device): + @callback + def _async_observe_update(self, tradfri_device): """Receive new state data for this light.""" self._refresh(tradfri_device) - self.schedule_update_ha_state() + self.hass.async_add_job(self.async_update_ha_state()) class TradfriLight(Light): - """The platform class required by Home Asisstant.""" + """The platform class required by Home Assistant.""" - def __init__(self, light, api, hass): + def __init__(self, light, api): """Initialize a Light.""" - self._hass = hass self._api = api self._light = None self._light_control = None @@ -151,12 +156,12 @@ def __init__(self, light, api, hass): self._features = None self._ok_temps = None - self._refresh(light) + self._async_refresh(light) @asyncio.coroutine def async_added_to_hass(self): """Start thread when added to hass.""" - self._start_observe() + self._async_start_observe() @property def should_poll(self): @@ -239,18 +244,22 @@ def async_turn_on(self, **kwargs): yield from self._api( self._light_control.set_hex_color(self._ok_temps[kelvin])) - def _start_observe(self, err=None): + @callback + def _async_start_observe(self, err=None): """Start observation of light.""" if err: _LOGGER.info("Observation failed for {}".format(self._name), err) - observe_command = self._light.observe(callback=self._observe_update, - err_callback=self._start_observe, + observe_command = self._light.observe(callback= + self._async_observe_update, + err_callback= + self._async_start_observe, duration=0) observe_task = self._api(observe_command) - ensure_future(observe_task, loop=self._hass.loop) + self.hass.async_add_job(observe_task) - def _refresh(self, light): + @callback + def _async_refresh(self, light): """Refresh the light data.""" self._light = light @@ -270,9 +279,10 @@ def _refresh(self, light): self._ok_temps = ALLOWED_TEMPERATURES.get( self._light.device_info.manufacturer) - def _observe_update(self, tradfri_device): + @callback + def _async_observe_update(self, tradfri_device): """Receive new state data for this light.""" - self._refresh(tradfri_device) + self._async_refresh(tradfri_device) # Handle Hue lights paired with the gateway # hex_color is 0 when bulb is unreachable @@ -280,4 +290,4 @@ def _observe_update(self, tradfri_device): self._rgb_color = color_util.rgb_hex_to_rgb_list( self._light_data.hex_color) - self.schedule_update_ha_state() + self.hass.async_add_job(self.async_update_ha_state()) From 836bb635314b27216a7d3ab85ab99eb10453709b Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Tue, 6 Jun 2017 06:50:29 +0100 Subject: [PATCH 08/43] Imports, formatting --- homeassistant/components/light/tradfri.py | 28 ++++++++--------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 6a9204bc0881b9..c19ff7d9668c17 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -8,12 +8,6 @@ import logging from homeassistant.core import callback - -try: - from asyncio import ensure_future -except ImportError: - from asyncio import async as ensure_future - from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light) @@ -120,12 +114,10 @@ def _async_start_observe(self, err=None): if err: _LOGGER.info("Observation failed for {}".format(self._name), err) - observe_command = self._group.observe(callback= - self._async_observe_update, - err_callback= - self._async_start_observe, - duration=0) - observe_task = self._api(observe_command) + cmd = self._group.observe(callback=self._async_observe_update, + err_callback=self._async_start_observe, + duration=0) + observe_task = self._api(cmd) self.hass.async_add_job(observe_task) @callback @@ -137,7 +129,7 @@ def _async_refresh(self, group): @callback def _async_observe_update(self, tradfri_device): """Receive new state data for this light.""" - self._refresh(tradfri_device) + self._async_refresh(tradfri_device) self.hass.async_add_job(self.async_update_ha_state()) @@ -250,12 +242,10 @@ def _async_start_observe(self, err=None): if err: _LOGGER.info("Observation failed for {}".format(self._name), err) - observe_command = self._light.observe(callback= - self._async_observe_update, - err_callback= - self._async_start_observe, - duration=0) - observe_task = self._api(observe_command) + cmd = self._light.observe(callback=self._async_observe_update, + err_callback=self._async_start_observe, + duration=0) + observe_task = self._api(cmd) self.hass.async_add_job(observe_task) @callback From 93bdbd0730f069ea55ab8076922c689c2df45dc0 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Tue, 6 Jun 2017 17:45:49 +0100 Subject: [PATCH 09/43] Docker updates, some minor async code changes. --- Dockerfile | 2 +- homeassistant/components/light/tradfri.py | 48 +++++++++++----------- homeassistant/components/tradfri.py | 2 +- requirements_all.txt | 2 +- virtualization/Docker/Dockerfile.dev | 2 +- virtualization/Docker/scripts/aiocoap | 23 +++++++++++ virtualization/Docker/scripts/coap_client | 14 ------- virtualization/Docker/setup_docker_prereqs | 6 +-- 8 files changed, 53 insertions(+), 46 deletions(-) create mode 100755 virtualization/Docker/scripts/aiocoap delete mode 100755 virtualization/Docker/scripts/coap_client diff --git a/Dockerfile b/Dockerfile index 8c4cd0f5440261..5b2618067af4b9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ MAINTAINER Paulus Schoutsen #ENV INSTALL_FFMPEG no #ENV INSTALL_LIBCEC no #ENV INSTALL_PHANTOMJS no -#ENV INSTALL_COAP_CLIENT no +#ENV INSTALL_COAP no VOLUME /config diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index c19ff7d9668c17..0f486e0c465e34 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -61,7 +61,7 @@ def __init__(self, light, api): self._group = light self._name = light.name - self._async_refresh(light) + self._refresh(light) @asyncio.coroutine def async_added_to_hass(self): @@ -103,10 +103,10 @@ def async_turn_off(self, **kwargs): def async_turn_on(self, **kwargs): """Instruct the group lights to turn on, or dim.""" if ATTR_BRIGHTNESS in kwargs: - yield from self._api( - self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS])) + self.hass.async_add_job(self._api( + self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS]))) else: - yield from self._api(self._group.set_state(1)) + self.hass.async_add_job(self._api(self._group.set_state(1))) @callback def _async_start_observe(self, err=None): @@ -114,22 +114,20 @@ def _async_start_observe(self, err=None): if err: _LOGGER.info("Observation failed for {}".format(self._name), err) - cmd = self._group.observe(callback=self._async_observe_update, + cmd = self._group.observe(callback=self._observe_update, err_callback=self._async_start_observe, duration=0) observe_task = self._api(cmd) self.hass.async_add_job(observe_task) - @callback - def _async_refresh(self, group): + def _refresh(self, group): """Refresh the light data.""" self._group = group self._name = group.name - @callback - def _async_observe_update(self, tradfri_device): + def _observe_update(self, tradfri_device): """Receive new state data for this light.""" - self._async_refresh(tradfri_device) + self._refresh(tradfri_device) self.hass.async_add_job(self.async_update_ha_state()) @@ -145,10 +143,10 @@ def __init__(self, light, api): self._light_data = None self._name = None self._rgb_color = None - self._features = None + self._features = SUPPORT_BRIGHTNESS self._ok_temps = None - self._async_refresh(light) + self._refresh(light) @asyncio.coroutine def async_added_to_hass(self): @@ -218,14 +216,16 @@ def async_turn_on(self, **kwargs): for ATTR_RGB_COLOR, this also supports Philips Hue bulbs. """ if ATTR_BRIGHTNESS in kwargs: - yield from self._api( - self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS])) + self.hass.async_add_job(self._api( + self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS]))) else: - yield from self._api(self._light_control.set_state(True)) + self.hass.async_add_job(self._api( + self._light_control.set_state(True))) if ATTR_RGB_COLOR in kwargs and self._light_data.hex_color is not None: - yield from self._api(self._light.light_control.set_hex_color( - color_util.color_rgb_to_hex(*kwargs[ATTR_RGB_COLOR]))) + self.hass.async_add_job(self._api( + self._light.light_control.set_hex_color( + color_util.color_rgb_to_hex(*kwargs[ATTR_RGB_COLOR])))) elif ATTR_COLOR_TEMP in kwargs and \ self._light_data.hex_color is not None and self._ok_temps: @@ -233,8 +233,8 @@ def async_turn_on(self, **kwargs): kwargs[ATTR_COLOR_TEMP]) # find closest allowed kelvin temp from user input kelvin = min(self._ok_temps.keys(), key=lambda x: abs(x - kelvin)) - yield from self._api( - self._light_control.set_hex_color(self._ok_temps[kelvin])) + self.hass.async_add_job(self._api( + self._light_control.set_hex_color(self._ok_temps[kelvin]))) @callback def _async_start_observe(self, err=None): @@ -242,14 +242,13 @@ def _async_start_observe(self, err=None): if err: _LOGGER.info("Observation failed for {}".format(self._name), err) - cmd = self._light.observe(callback=self._async_observe_update, + cmd = self._light.observe(callback=self._observe_update, err_callback=self._async_start_observe, duration=0) observe_task = self._api(cmd) self.hass.async_add_job(observe_task) - @callback - def _async_refresh(self, light): + def _refresh(self, light): """Refresh the light data.""" self._light = light @@ -269,10 +268,9 @@ def _async_refresh(self, light): self._ok_temps = ALLOWED_TEMPERATURES.get( self._light.device_info.manufacturer) - @callback - def _async_observe_update(self, tradfri_device): + def _observe_update(self, tradfri_device): """Receive new state data for this light.""" - self._async_refresh(tradfri_device) + self._refresh(tradfri_device) # Handle Hue lights paired with the gateway # hex_color is 0 when bulb is unreachable diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index a64d1607dcba77..ddf8f92ac5278e 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -18,7 +18,7 @@ from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI REQUIREMENTS = ['https://github.com/ggravlingen/pytradfri/archive/' - '39da698c225dce712bf14e3edd9d8fdfd10153f1.zip#pytradfri==2.0'] + '7f06c722604ee7a2ad5c310ab7c313c42496369f.zip#pytradfri==2.0'] DOMAIN = 'tradfri' CONFIG_FILE = 'tradfri.conf' diff --git a/requirements_all.txt b/requirements_all.txt index ec724264154016..5e070aceb5bb8a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -277,7 +277,7 @@ https://github.com/LinuxChristian/pyW215/archive/v0.4.zip#pyW215==0.4 https://github.com/aparraga/braviarc/archive/0.3.7.zip#braviarc==0.3.7 # homeassistant.components.tradfri -https://github.com/ggravlingen/pytradfri/archive/39da698c225dce712bf14e3edd9d8fdfd10153f1.zip#pytradfri==2.0 +https://github.com/ggravlingen/pytradfri/archive/7f06c722604ee7a2ad5c310ab7c313c42496369f.zip#pytradfri==2.0 # homeassistant.components.media_player.spotify https://github.com/happyleavesaoc/spotipy/archive/544614f4b1d508201d363e84e871f86c90aa26b2.zip#spotipy==2.4.4 diff --git a/virtualization/Docker/Dockerfile.dev b/virtualization/Docker/Dockerfile.dev index 2f40ea5f409a5b..8088135c6530d4 100644 --- a/virtualization/Docker/Dockerfile.dev +++ b/virtualization/Docker/Dockerfile.dev @@ -11,7 +11,7 @@ MAINTAINER Paulus Schoutsen #ENV INSTALL_FFMPEG no #ENV INSTALL_LIBCEC no #ENV INSTALL_PHANTOMJS no -#ENV INSTALL_COAP_CLIENT no +#ENV INSTALL_COAP no VOLUME /config diff --git a/virtualization/Docker/scripts/aiocoap b/virtualization/Docker/scripts/aiocoap new file mode 100755 index 00000000000000..9e10c1b763f544 --- /dev/null +++ b/virtualization/Docker/scripts/aiocoap @@ -0,0 +1,23 @@ +#!/bin/sh +# Installs a modified coap client with support for dtls for use with IKEA Tradfri + +# Stop on errors +set -e + +apt-get install -y --no-install-recommends git autoconf automake libtool + +mkdir -p /usr/src/build +cd /usr/src/build +git clone --depth 1 https://git.fslab.de/jkonra2m/tinydtls +cd tinydtls +autoreconf +./configure --with-ecc +make +cd cython +pip3 install cython +python3 setup.py build_ext --inplace + +cd .. +git clone --depth 1 -b tinydtls https://github.com/chrysn/aiocoap/ +cd aiocoap +python3 setup.py develop \ No newline at end of file diff --git a/virtualization/Docker/scripts/coap_client b/virtualization/Docker/scripts/coap_client deleted file mode 100755 index fa16d14c0cba68..00000000000000 --- a/virtualization/Docker/scripts/coap_client +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# Installs a modified coap client with support for dtls for use with IKEA Tradfri - -# Stop on errors -set -e - -apt-get install -y --no-install-recommends git autoconf automake libtool - -git clone --depth 1 --recursive -b dtls https://github.com/home-assistant/libcoap.git -cd libcoap -./autogen.sh -./configure --disable-documentation --disable-shared --without-debug CFLAGS="-D COAP_DEBUG_FD=stderr" -make -make install diff --git a/virtualization/Docker/setup_docker_prereqs b/virtualization/Docker/setup_docker_prereqs index a6bf716312d743..05ba455999cb13 100755 --- a/virtualization/Docker/setup_docker_prereqs +++ b/virtualization/Docker/setup_docker_prereqs @@ -9,7 +9,7 @@ INSTALL_OPENALPR="${INSTALL_OPENALPR:-yes}" INSTALL_FFMPEG="${INSTALL_FFMPEG:-yes}" INSTALL_LIBCEC="${INSTALL_LIBCEC:-yes}" INSTALL_PHANTOMJS="${INSTALL_PHANTOMJS:-yes}" -INSTALL_COAP_CLIENT="${INSTALL_COAP_CLIENT:-yes}" +INSTALL_COAP="${INSTALL_COAP:-yes}" # Required debian packages for running hass or components PACKAGES=( @@ -58,8 +58,8 @@ if [ "$INSTALL_PHANTOMJS" == "yes" ]; then virtualization/Docker/scripts/phantomjs fi -if [ "$INSTALL_COAP_CLIENT" == "yes" ]; then - virtualization/Docker/scripts/coap_client +if [ "$INSTALL_COAP" == "yes" ]; then + virtualization/Docker/scripts/aiocoap fi # Remove packages From 6a136130e590982d77eadd0bbed01a843afb5568 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Tue, 6 Jun 2017 18:16:39 +0100 Subject: [PATCH 10/43] Lint --- homeassistant/components/light/tradfri.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 0f486e0c465e34..6f8a92deb6e1bf 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -112,7 +112,7 @@ def async_turn_on(self, **kwargs): def _async_start_observe(self, err=None): """Start observation of light.""" if err: - _LOGGER.info("Observation failed for {}".format(self._name), err) + _LOGGER.info("Observation failed for %", self._name, exc_info=err) cmd = self._group.observe(callback=self._observe_update, err_callback=self._async_start_observe, @@ -240,7 +240,7 @@ def async_turn_on(self, **kwargs): def _async_start_observe(self, err=None): """Start observation of light.""" if err: - _LOGGER.info("Observation failed for {}".format(self._name), err) + _LOGGER.info("Observation failed for %", self._name, exc_info=err) cmd = self._light.observe(callback=self._observe_update, err_callback=self._async_start_observe, From b1e1fc2450e955aa45568796cc3c65578b10342a Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Tue, 6 Jun 2017 18:51:05 +0100 Subject: [PATCH 11/43] Lint --- homeassistant/components/light/tradfri.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 6f8a92deb6e1bf..c205a8a42e0d5d 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -112,7 +112,8 @@ def async_turn_on(self, **kwargs): def _async_start_observe(self, err=None): """Start observation of light.""" if err: - _LOGGER.info("Observation failed for %", self._name, exc_info=err) + _LOGGER.info("Observation failed for %s", self._name, + exc_info=err) cmd = self._group.observe(callback=self._observe_update, err_callback=self._async_start_observe, @@ -240,7 +241,8 @@ def async_turn_on(self, **kwargs): def _async_start_observe(self, err=None): """Start observation of light.""" if err: - _LOGGER.info("Observation failed for %", self._name, exc_info=err) + _LOGGER.info("Observation failed for %s", self._name, + exc_info=err) cmd = self._light.observe(callback=self._observe_update, err_callback=self._async_start_observe, From b6ed0ed6866122d24271065e0e4c5b5bc29b1838 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sat, 10 Jun 2017 17:24:37 +0100 Subject: [PATCH 12/43] Update pytradfri --- homeassistant/components/tradfri.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index ddf8f92ac5278e..ef72da22c8b78b 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -18,7 +18,7 @@ from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI REQUIREMENTS = ['https://github.com/ggravlingen/pytradfri/archive/' - '7f06c722604ee7a2ad5c310ab7c313c42496369f.zip#pytradfri==2.0'] + 'cb273aca8b1c6899a0361231f03b0ad695b769be.zip#pytradfri==2.0'] DOMAIN = 'tradfri' CONFIG_FILE = 'tradfri.conf' diff --git a/requirements_all.txt b/requirements_all.txt index b3006e9fa7d78d..67b6c80df17818 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -277,7 +277,7 @@ https://github.com/LinuxChristian/pyW215/archive/v0.4.zip#pyW215==0.4 https://github.com/aparraga/braviarc/archive/0.3.7.zip#braviarc==0.3.7 # homeassistant.components.tradfri -https://github.com/ggravlingen/pytradfri/archive/7f06c722604ee7a2ad5c310ab7c313c42496369f.zip#pytradfri==2.0 +https://github.com/ggravlingen/pytradfri/archive/cb273aca8b1c6899a0361231f03b0ad695b769be.zip#pytradfri==2.0 # homeassistant.components.media_player.spotify https://github.com/happyleavesaoc/spotipy/archive/544614f4b1d508201d363e84e871f86c90aa26b2.zip#spotipy==2.4.4 From dd6d5b6f749f5aac3b2c4d74df15a75bc171c5d3 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Wed, 14 Jun 2017 17:20:07 +0100 Subject: [PATCH 13/43] Minor updates for release version --- homeassistant/components/tradfri.py | 9 ++++----- requirements_all.txt | 6 +++--- virtualization/Docker/scripts/aiocoap | 13 +++++-------- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index ef72da22c8b78b..eebbcf7abeeacd 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -17,8 +17,7 @@ from homeassistant.loader import get_component from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI -REQUIREMENTS = ['https://github.com/ggravlingen/pytradfri/archive/' - 'cb273aca8b1c6899a0361231f03b0ad695b769be.zip#pytradfri==2.0'] +REQUIREMENTS = ['pytradfri==2.0'] DOMAIN = 'tradfri' CONFIG_FILE = 'tradfri.conf' @@ -116,15 +115,15 @@ def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): from pytradfri.api.aiocoap_api import api_factory try: - api = yield from api_factory(host, key) + api = yield from api_factory(host, key, loop=hass.loop) hass.data[KEY_API] = api except RequestError: return False gateway = Gateway() gateway_id_cmd = gateway.get_gateway_info() - gateway_id_result = yield from api(gateway_id_cmd) - gateway_id = gateway_id_result.id + yield from api(gateway_id_cmd) + gateway_id = gateway_id_cmd.result.id hass.data.setdefault(KEY_GATEWAY, {}) gateways = hass.data[KEY_GATEWAY] diff --git a/requirements_all.txt b/requirements_all.txt index e3718e858516a4..d1e474c7569e52 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -279,9 +279,6 @@ https://github.com/LinuxChristian/pyW215/archive/v0.4.zip#pyW215==0.4 # homeassistant.components.media_player.braviatv https://github.com/aparraga/braviarc/archive/0.3.7.zip#braviarc==0.3.7 -# homeassistant.components.tradfri -https://github.com/ggravlingen/pytradfri/archive/cb273aca8b1c6899a0361231f03b0ad695b769be.zip#pytradfri==2.0 - # homeassistant.components.media_player.spotify https://github.com/happyleavesaoc/spotipy/archive/544614f4b1d508201d363e84e871f86c90aa26b2.zip#spotipy==2.4.4 @@ -735,6 +732,9 @@ python_openzwave==0.4.0.31 # homeassistant.components.device_tracker.trackr pytrackr==0.0.5 +# homeassistant.components.tradfri +pytradfri==2.0 + # homeassistant.components.device_tracker.unifi pyunifi==2.12 diff --git a/virtualization/Docker/scripts/aiocoap b/virtualization/Docker/scripts/aiocoap index 9e10c1b763f544..7c30993a968feb 100755 --- a/virtualization/Docker/scripts/aiocoap +++ b/virtualization/Docker/scripts/aiocoap @@ -4,20 +4,17 @@ # Stop on errors set -e -apt-get install -y --no-install-recommends git autoconf automake libtool - mkdir -p /usr/src/build cd /usr/src/build + git clone --depth 1 https://git.fslab.de/jkonra2m/tinydtls cd tinydtls autoreconf -./configure --with-ecc -make +./configure --with-ecc --without-debug cd cython -pip3 install cython -python3 setup.py build_ext --inplace +python3 setup.py install -cd .. +cd ../.. git clone --depth 1 -b tinydtls https://github.com/chrysn/aiocoap/ cd aiocoap -python3 setup.py develop \ No newline at end of file +python3 -m pip install . From 27ff361d7c64bf66e679df4e1cddd9ebc5be8acf Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Wed, 14 Jun 2017 18:20:16 +0100 Subject: [PATCH 14/43] Build fixes --- Dockerfile | 2 +- homeassistant/components/tradfri.py | 6 +++--- virtualization/Docker/Dockerfile.dev | 4 ++-- virtualization/Docker/scripts/aiocoap | 2 ++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5b2618067af4b9..8ff4ba801db733 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,7 @@ RUN virtualization/Docker/setup_docker_prereqs # Install hass component dependencies COPY requirements_all.txt requirements_all.txt RUN pip3 install --no-cache-dir -r requirements_all.txt && \ - pip3 install --no-cache-dir mysqlclient psycopg2 uvloop cchardet + pip3 install --no-cache-dir mysqlclient psycopg2 cchardet # Copy source COPY . . diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index eebbcf7abeeacd..092cd08228ccba 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -121,9 +121,9 @@ def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): return False gateway = Gateway() - gateway_id_cmd = gateway.get_gateway_info() - yield from api(gateway_id_cmd) - gateway_id = gateway_id_cmd.result.id + gateway_info_cmd = gateway.get_gateway_info() + gateway_info_result = yield from api(gateway_info_cmd) + gateway_id = gateway_info_result.id hass.data.setdefault(KEY_GATEWAY, {}) gateways = hass.data[KEY_GATEWAY] diff --git a/virtualization/Docker/Dockerfile.dev b/virtualization/Docker/Dockerfile.dev index 8088135c6530d4..9c0ee52c413f29 100644 --- a/virtualization/Docker/Dockerfile.dev +++ b/virtualization/Docker/Dockerfile.dev @@ -25,7 +25,7 @@ RUN virtualization/Docker/setup_docker_prereqs # Install hass component dependencies COPY requirements_all.txt requirements_all.txt RUN pip3 install --no-cache-dir -r requirements_all.txt && \ - pip3 install --no-cache-dir mysqlclient psycopg2 uvloop cchardet + pip3 install --no-cache-dir mysqlclient psycopg2 cchardet # BEGIN: Development additions @@ -48,4 +48,4 @@ RUN tox -e py36 --notest # Copy source COPY . . -CMD [ "python", "-m", "homeassistant", "--config", "/config" ] \ No newline at end of file +CMD [ "python", "-m", "homeassistant", "--config", "/config" ] diff --git a/virtualization/Docker/scripts/aiocoap b/virtualization/Docker/scripts/aiocoap index 7c30993a968feb..7b2c83f48ea5dc 100755 --- a/virtualization/Docker/scripts/aiocoap +++ b/virtualization/Docker/scripts/aiocoap @@ -4,6 +4,8 @@ # Stop on errors set -e +python3 -m pip install cython + mkdir -p /usr/src/build cd /usr/src/build From e432e7ffd82728607f3ae28f3d86f2fb0caba207 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Wed, 14 Jun 2017 20:25:35 +0100 Subject: [PATCH 15/43] Retry observation if failed --- homeassistant/components/light/tradfri.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index c205a8a42e0d5d..0aa74888241cb6 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -119,7 +119,12 @@ def _async_start_observe(self, err=None): err_callback=self._async_start_observe, duration=0) observe_task = self._api(cmd) - self.hass.async_add_job(observe_task) + try: + yield from observe_task() + except: + _LOGGER.info("Observation failed, trying again.") + asyncio.sleep(5) + self._async_start_observe() def _refresh(self, group): """Refresh the light data.""" @@ -248,7 +253,12 @@ def _async_start_observe(self, err=None): err_callback=self._async_start_observe, duration=0) observe_task = self._api(cmd) - self.hass.async_add_job(observe_task) + try: + yield from observe_task() + except: + _LOGGER.info("Observation failed, trying again.") + asyncio.sleep(5) + self._async_start_observe() def _refresh(self, light): """Refresh the light data.""" From 748a7cfa2dcd2c1f6482c963f65cea27b54d5b46 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Wed, 14 Jun 2017 20:49:42 +0100 Subject: [PATCH 16/43] Revert --- homeassistant/components/light/tradfri.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 0aa74888241cb6..bd551f4e488d89 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -118,13 +118,7 @@ def _async_start_observe(self, err=None): cmd = self._group.observe(callback=self._observe_update, err_callback=self._async_start_observe, duration=0) - observe_task = self._api(cmd) - try: - yield from observe_task() - except: - _LOGGER.info("Observation failed, trying again.") - asyncio.sleep(5) - self._async_start_observe() + self.hass.async_add_job(self._api(cmd)) def _refresh(self, group): """Refresh the light data.""" @@ -252,13 +246,7 @@ def _async_start_observe(self, err=None): cmd = self._light.observe(callback=self._observe_update, err_callback=self._async_start_observe, duration=0) - observe_task = self._api(cmd) - try: - yield from observe_task() - except: - _LOGGER.info("Observation failed, trying again.") - asyncio.sleep(5) - self._async_start_observe() + self.hass.async_add_job(self._api(cmd)) def _refresh(self, light): """Refresh the light data.""" From 0158959eae2df102626ba6d3f70819078b58634f Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 15 Jun 2017 17:48:40 +0100 Subject: [PATCH 17/43] Additional logging, fix returns --- homeassistant/components/light/tradfri.py | 11 +++++------ homeassistant/components/tradfri.py | 7 ++++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index bd551f4e488d89..13457a9e658b93 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -96,8 +96,7 @@ def brightness(self): @asyncio.coroutine def async_turn_off(self, **kwargs): """Instruct the group lights to turn off.""" - result = yield from self._api(self._group.set_state(0)) - return result + self.hass.async_add_job(self._api(self._group.set_state(0))) @asyncio.coroutine def async_turn_on(self, **kwargs): @@ -204,8 +203,8 @@ def rgb_color(self): @asyncio.coroutine def async_turn_off(self, **kwargs): """Instruct the light to turn off.""" - result = yield from self._api(self._light_control.set_state(False)) - return result + self.hass.async_add_job(self._api( + self._light_control.set_state(False))) @asyncio.coroutine def async_turn_on(self, **kwargs): @@ -237,11 +236,11 @@ def async_turn_on(self, **kwargs): self._light_control.set_hex_color(self._ok_temps[kelvin]))) @callback - def _async_start_observe(self, err=None): + def _async_start_observe(self, exc=None): """Start observation of light.""" if err: _LOGGER.info("Observation failed for %s", self._name, - exc_info=err) + exc_info=exc) cmd = self._light.observe(callback=self._observe_update, err_callback=self._async_start_observe, diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 092cd08228ccba..0788ff7ec67ee9 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -112,12 +112,17 @@ def gateway_discovered(service, info): def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): """Create a gateway.""" from pytradfri import Gateway, RequestError - from pytradfri.api.aiocoap_api import api_factory + try: + from pytradfri.api.aiocoap_api import api_factory + except ImportError: + _LOGGER.exception("Looks like something isn't installed!") + return False try: api = yield from api_factory(host, key, loop=hass.loop) hass.data[KEY_API] = api except RequestError: + _LOGGER.exception("Tradfri setup failed.") return False gateway = Gateway() From 597464d61050144b3d9bde0b0e5bc26ed1b31503 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 15 Jun 2017 17:50:40 +0100 Subject: [PATCH 18/43] Fix rename --- homeassistant/components/light/tradfri.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 13457a9e658b93..0be3a2e221f9aa 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -108,11 +108,11 @@ def async_turn_on(self, **kwargs): self.hass.async_add_job(self._api(self._group.set_state(1))) @callback - def _async_start_observe(self, err=None): + def _async_start_observe(self, exc=None): """Start observation of light.""" - if err: + if exc: _LOGGER.info("Observation failed for %s", self._name, - exc_info=err) + exc_info=exc) cmd = self._group.observe(callback=self._observe_update, err_callback=self._async_start_observe, @@ -238,7 +238,7 @@ def async_turn_on(self, **kwargs): @callback def _async_start_observe(self, exc=None): """Start observation of light.""" - if err: + if exc: _LOGGER.info("Observation failed for %s", self._name, exc_info=exc) From 10887e2272c7a6a29088f83a71bf6e8ce8235764 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 22 Jun 2017 18:24:41 +0100 Subject: [PATCH 19/43] Bump version --- homeassistant/components/tradfri.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 0788ff7ec67ee9..3cb38d4a3d04b3 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -17,7 +17,7 @@ from homeassistant.loader import get_component from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI -REQUIREMENTS = ['pytradfri==2.0'] +REQUIREMENTS = ['pytradfri==2.1'] DOMAIN = 'tradfri' CONFIG_FILE = 'tradfri.conf' diff --git a/requirements_all.txt b/requirements_all.txt index 6fa0d8dcc32085..69a7c481043668 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -742,7 +742,7 @@ python_openzwave==0.4.0.31 pytrackr==0.0.5 # homeassistant.components.tradfri -pytradfri==2.0 +pytradfri==2.1 # homeassistant.components.device_tracker.unifi pyunifi==2.13 From 2e7e6c1c20b7cddd615dc4254022bfb37d50bdd8 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 22 Jun 2017 19:38:10 +0100 Subject: [PATCH 20/43] Bump version --- homeassistant/components/tradfri.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 3cb38d4a3d04b3..5a1a730c0579fc 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -17,7 +17,7 @@ from homeassistant.loader import get_component from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI -REQUIREMENTS = ['pytradfri==2.1'] +REQUIREMENTS = ['pytradfri==2.1.1'] DOMAIN = 'tradfri' CONFIG_FILE = 'tradfri.conf' diff --git a/requirements_all.txt b/requirements_all.txt index 69a7c481043668..142dec1b8e0ef7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -742,7 +742,7 @@ python_openzwave==0.4.0.31 pytrackr==0.0.5 # homeassistant.components.tradfri -pytradfri==2.1 +pytradfri==2.1.1 # homeassistant.components.device_tracker.unifi pyunifi==2.13 From 2d6b3dffac566db91e181083dac2ec0ac330c613 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 22 Jun 2017 21:19:24 +0100 Subject: [PATCH 21/43] Support transitions --- homeassistant/components/light/tradfri.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 0be3a2e221f9aa..62262ab6d292b7 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -10,7 +10,7 @@ from homeassistant.core import callback from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, - SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light) + SUPPORT_TRANSITION, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light) from homeassistant.components.light import \ PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA from homeassistant.components.tradfri import KEY_GATEWAY, KEY_TRADFRI_GROUPS, \ @@ -23,6 +23,7 @@ PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA IKEA = 'IKEA of Sweden' TRADFRI_LIGHT_MANAGER = 'Tradfri Light Manager' +SUPPORTED_FEATURES = (SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION) ALLOWED_TEMPERATURES = { IKEA: {2200: 'efd275', 2700: 'f1e0b5', 4000: 'f5faf6'} } @@ -76,7 +77,7 @@ def should_poll(self): @property def supported_features(self): """Flag supported features.""" - return SUPPORT_BRIGHTNESS + return SUPPORTED_FEATURES @property def name(self): @@ -102,8 +103,10 @@ def async_turn_off(self, **kwargs): def async_turn_on(self, **kwargs): """Instruct the group lights to turn on, or dim.""" if ATTR_BRIGHTNESS in kwargs: + transition = kwargs[ATTR_TRANSITION] self.hass.async_add_job(self._api( - self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS]))) + self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS], + transition_time=transition))) else: self.hass.async_add_job(self._api(self._group.set_state(1))) @@ -142,7 +145,7 @@ def __init__(self, light, api): self._light_data = None self._name = None self._rgb_color = None - self._features = SUPPORT_BRIGHTNESS + self._features = SUPPORTED_FEATURES self._ok_temps = None self._refresh(light) @@ -215,8 +218,10 @@ def async_turn_on(self, **kwargs): for ATTR_RGB_COLOR, this also supports Philips Hue bulbs. """ if ATTR_BRIGHTNESS in kwargs: + transition = kwargs[ATTR_TRANSITION] self.hass.async_add_job(self._api( - self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS]))) + self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS], + transition_time=transition))) else: self.hass.async_add_job(self._api( self._light_control.set_state(True))) @@ -256,7 +261,7 @@ def _refresh(self, light): self._light_data = light.light_control.lights[0] self._name = light.name self._rgb_color = None - self._features = SUPPORT_BRIGHTNESS + self._features = SUPPORTED_FEATURES if self._light_data.hex_color is not None: if self._light.device_info.manufacturer == IKEA: From d4255c235c6f97d5674127ebf1e647ea915cd988 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 22 Jun 2017 21:21:49 +0100 Subject: [PATCH 22/43] Lint --- homeassistant/components/light/tradfri.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 62262ab6d292b7..17960df0763de8 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -9,8 +9,9 @@ from homeassistant.core import callback from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, SUPPORT_BRIGHTNESS, - SUPPORT_TRANSITION, SUPPORT_COLOR_TEMP, SUPPORT_RGB_COLOR, Light) + ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_RGB_COLOR, ATTR_TRANSITION, + SUPPORT_BRIGHTNESS, SUPPORT_TRANSITION, SUPPORT_COLOR_TEMP, + SUPPORT_RGB_COLOR, Light) from homeassistant.components.light import \ PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA from homeassistant.components.tradfri import KEY_GATEWAY, KEY_TRADFRI_GROUPS, \ @@ -221,7 +222,7 @@ def async_turn_on(self, **kwargs): transition = kwargs[ATTR_TRANSITION] self.hass.async_add_job(self._api( self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS], - transition_time=transition))) + transition_time=transition))) else: self.hass.async_add_job(self._api( self._light_control.set_state(True))) From 0a3f3d5a51ce16998a014b74913da7e31b241e3d Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sat, 24 Jun 2017 10:21:29 +0100 Subject: [PATCH 23/43] Fix transitions --- homeassistant/components/light/tradfri.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 17960df0763de8..8187124698ce5b 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -103,11 +103,13 @@ def async_turn_off(self, **kwargs): @asyncio.coroutine def async_turn_on(self, **kwargs): """Instruct the group lights to turn on, or dim.""" + keys = {} + if ATTR_TRANSITION in kwargs: + keys['transition_time'] = int(kwargs[ATTR_TRANSITION]) + if ATTR_BRIGHTNESS in kwargs: - transition = kwargs[ATTR_TRANSITION] self.hass.async_add_job(self._api( - self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS], - transition_time=transition))) + self._group.set_dimmer(kwargs[ATTR_BRIGHTNESS], **keys))) else: self.hass.async_add_job(self._api(self._group.set_state(1))) @@ -218,11 +220,14 @@ def async_turn_on(self, **kwargs): After adding "self._light_data.hexcolor is not None" for ATTR_RGB_COLOR, this also supports Philips Hue bulbs. """ + keys = {} + if ATTR_TRANSITION in kwargs: + keys['transition_time'] = int(kwargs[ATTR_TRANSITION]) + if ATTR_BRIGHTNESS in kwargs: - transition = kwargs[ATTR_TRANSITION] self.hass.async_add_job(self._api( self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS], - transition_time=transition))) + **keys))) else: self.hass.async_add_job(self._api( self._light_control.set_state(True))) From 462c64136246159f7f9decf266d94c5d374f995f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 24 Jun 2017 18:14:19 -0700 Subject: [PATCH 24/43] Update Dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 8891c43de1e2d6..687e1a5c00e6da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,7 @@ RUN virtualization/Docker/setup_docker_prereqs # Install hass component dependencies COPY requirements_all.txt requirements_all.txt +# Not installing uvloop because it doesn't work with pytradfri - PR #7815 # Uninstall enum34 because some depenndecies install it but breaks Python 3.4+. # See PR #8103 for more info. RUN pip3 install --no-cache-dir -r requirements_all.txt && \ From a45c7dc9bb69c26eb225833bb8ff01f08be9e49f Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Tue, 27 Jun 2017 19:14:46 +0100 Subject: [PATCH 25/43] Set temp first --- homeassistant/components/light/tradfri.py | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 8187124698ce5b..ab69735a50c230 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -220,18 +220,6 @@ def async_turn_on(self, **kwargs): After adding "self._light_data.hexcolor is not None" for ATTR_RGB_COLOR, this also supports Philips Hue bulbs. """ - keys = {} - if ATTR_TRANSITION in kwargs: - keys['transition_time'] = int(kwargs[ATTR_TRANSITION]) - - if ATTR_BRIGHTNESS in kwargs: - self.hass.async_add_job(self._api( - self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS], - **keys))) - else: - self.hass.async_add_job(self._api( - self._light_control.set_state(True))) - if ATTR_RGB_COLOR in kwargs and self._light_data.hex_color is not None: self.hass.async_add_job(self._api( self._light.light_control.set_hex_color( @@ -246,6 +234,18 @@ def async_turn_on(self, **kwargs): self.hass.async_add_job(self._api( self._light_control.set_hex_color(self._ok_temps[kelvin]))) + keys = {} + if ATTR_TRANSITION in kwargs: + keys['transition_time'] = int(kwargs[ATTR_TRANSITION]) + + if ATTR_BRIGHTNESS in kwargs: + self.hass.async_add_job(self._api( + self._light_control.set_dimmer(kwargs[ATTR_BRIGHTNESS], + **keys))) + else: + self.hass.async_add_job(self._api( + self._light_control.set_state(True))) + @callback def _async_start_observe(self, exc=None): """Start observation of light.""" From 0c841c30b2bad9b7a2e979f9e6106d91bfb9167e Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sat, 1 Jul 2017 08:31:07 +0100 Subject: [PATCH 26/43] Observation error handling --- homeassistant/components/light/tradfri.py | 30 +++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index ab69735a50c230..6731a68a382046 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -116,14 +116,19 @@ def async_turn_on(self, **kwargs): @callback def _async_start_observe(self, exc=None): """Start observation of light.""" + from pytradfri.error import PyTradFriError if exc: - _LOGGER.info("Observation failed for %s", self._name, + _LOGGER.warn("Observation failed for %s", self._name, exc_info=exc) - cmd = self._group.observe(callback=self._observe_update, - err_callback=self._async_start_observe, - duration=0) - self.hass.async_add_job(self._api(cmd)) + try: + cmd = self._group.observe(callback=self._observe_update, + err_callback=self._async_start_observe, + duration=0) + self.hass.async_add_job(self._api(cmd)) + except PyTradFriError as e: + _LOGGER.warn("Observation failed, trying again", exc_info=e) + self._async_start_observe() def _refresh(self, group): """Refresh the light data.""" @@ -249,14 +254,19 @@ def async_turn_on(self, **kwargs): @callback def _async_start_observe(self, exc=None): """Start observation of light.""" + from pytradfri.error import PyTradFriError if exc: - _LOGGER.info("Observation failed for %s", self._name, + _LOGGER.warn("Observation failed for %s", self._name, exc_info=exc) - cmd = self._light.observe(callback=self._observe_update, - err_callback=self._async_start_observe, - duration=0) - self.hass.async_add_job(self._api(cmd)) + try: + cmd = self._light.observe(callback=self._observe_update, + err_callback=self._async_start_observe, + duration=0) + self.hass.async_add_job(self._api(cmd)) + except PyTradFriError as e: + _LOGGER.warn("Observation failed, trying again", exc_info=e) + self._async_start_observe() def _refresh(self, light): """Refresh the light data.""" From 5906591d06756022197ddf441c0ee3ab65bb381a Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sat, 1 Jul 2017 09:20:58 +0100 Subject: [PATCH 27/43] Lint --- homeassistant/components/light/tradfri.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 6731a68a382046..eac5143818eb0f 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -118,16 +118,16 @@ def _async_start_observe(self, exc=None): """Start observation of light.""" from pytradfri.error import PyTradFriError if exc: - _LOGGER.warn("Observation failed for %s", self._name, - exc_info=exc) + _LOGGER.warning("Observation failed for %s", self._name, + exc_info=exc) try: cmd = self._group.observe(callback=self._observe_update, err_callback=self._async_start_observe, duration=0) self.hass.async_add_job(self._api(cmd)) - except PyTradFriError as e: - _LOGGER.warn("Observation failed, trying again", exc_info=e) + except PyTradFriError as exc: + _LOGGER.warning("Observation failed, trying again", exc_info=exc) self._async_start_observe() def _refresh(self, group): @@ -256,16 +256,16 @@ def _async_start_observe(self, exc=None): """Start observation of light.""" from pytradfri.error import PyTradFriError if exc: - _LOGGER.warn("Observation failed for %s", self._name, - exc_info=exc) + _LOGGER.warning("Observation failed for %s", self._name, + exc_info=exc) try: cmd = self._light.observe(callback=self._observe_update, err_callback=self._async_start_observe, duration=0) self.hass.async_add_job(self._api(cmd)) - except PyTradFriError as e: - _LOGGER.warn("Observation failed, trying again", exc_info=e) + except PyTradFriError as exc: + _LOGGER.warning("Observation failed, trying again", exc_info=e) self._async_start_observe() def _refresh(self, light): From 814f42066a504c8df35d6cadc0e74102c9718eaa Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sat, 1 Jul 2017 09:28:26 +0100 Subject: [PATCH 28/43] Lint --- homeassistant/components/light/tradfri.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index eac5143818eb0f..5518e17d6b3073 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -265,7 +265,7 @@ def _async_start_observe(self, exc=None): duration=0) self.hass.async_add_job(self._api(cmd)) except PyTradFriError as exc: - _LOGGER.warning("Observation failed, trying again", exc_info=e) + _LOGGER.warning("Observation failed, trying again", exc_info=exc) self._async_start_observe() def _refresh(self, light): From 14af0496a27fde9c4fdb347e4ba24c9df63df048 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Mon, 3 Jul 2017 20:50:24 +0100 Subject: [PATCH 29/43] Lint --- homeassistant/components/light/tradfri.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 5518e17d6b3073..53e82fcaf8149f 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -126,8 +126,8 @@ def _async_start_observe(self, exc=None): err_callback=self._async_start_observe, duration=0) self.hass.async_add_job(self._api(cmd)) - except PyTradFriError as exc: - _LOGGER.warning("Observation failed, trying again", exc_info=exc) + except PyTradFriError as err: + _LOGGER.warning("Observation failed, trying again", exc_info=err) self._async_start_observe() def _refresh(self, group): @@ -264,8 +264,8 @@ def _async_start_observe(self, exc=None): err_callback=self._async_start_observe, duration=0) self.hass.async_add_job(self._api(cmd)) - except PyTradFriError as exc: - _LOGGER.warning("Observation failed, trying again", exc_info=exc) + except PyTradFriError as err: + _LOGGER.warning("Observation failed, trying again", exc_info=err) self._async_start_observe() def _refresh(self, light): From aef1005f16045462c6f27aa56c7e597516eed2bf Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 31 Aug 2017 13:25:47 +0100 Subject: [PATCH 30/43] Merge upstream changes --- homeassistant/components/light/tradfri.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 1103761f64c73d..aae75b6762b04e 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -239,10 +239,8 @@ def async_turn_on(self, **kwargs): self._light_data.hex_color is not None and self._ok_temps: kelvin = color_util.color_temperature_mired_to_kelvin( kwargs[ATTR_COLOR_TEMP]) - # find closest allowed kelvin temp from user input - kelvin = min(self._ok_temps.keys(), key=lambda x: abs(x - kelvin)) self.hass.async_add_job(self._api( - self._light_control.set_hex_color(self._ok_temps[kelvin]))) + self._light_control.set_kelvin_color(kelvin))) keys = {} if ATTR_TRANSITION in kwargs: From 76b1913a9e79371c6aaf9bfa5ab44a1f14bafe19 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 31 Aug 2017 14:00:44 +0100 Subject: [PATCH 31/43] Fix bugs --- homeassistant/components/light/tradfri.py | 4 ++-- homeassistant/components/tradfri.py | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index aae75b6762b04e..5e3a3144e3633c 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -160,13 +160,13 @@ def __init__(self, light, api): @property def min_mireds(self): - """Return the coldest color_temp that this light supports.""" + """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.""" + """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) diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index e319f038b11c37..3843767485943e 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -24,7 +24,6 @@ KEY_GATEWAY = 'tradfri_gateway' KEY_API = 'tradfri_api' KEY_TRADFRI_GROUPS = 'tradfri_allow_tradfri_groups' -KEY_API = 'tradfri_api' CONF_ALLOW_TRADFRI_GROUPS = 'allow_tradfri_groups' DEFAULT_ALLOW_TRADFRI_GROUPS = True @@ -120,14 +119,12 @@ def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): try: api = yield from api_factory(host, key, loop=hass.loop) - hass.data[KEY_API] = api except RequestError: _LOGGER.exception("Tradfri setup failed.") return False gateway = Gateway() - gateway_info_cmd = gateway.get_gateway_info() - gateway_info_result = yield from api(gateway_info_cmd) + gateway_info_result = yield from api(gateway.get_gateway_info()) gateway_id = gateway_info_result.id hass.data.setdefault(KEY_API, {}) hass.data.setdefault(KEY_GATEWAY, {}) From 719c1f14a13eb299ffa51f69b2173ac82b9c18ba Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 31 Aug 2017 14:26:58 +0100 Subject: [PATCH 32/43] Fix bugs --- homeassistant/components/light/tradfri.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 5e3a3144e3633c..61779aadc6a21d 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -37,7 +37,6 @@ def async_setup_platform(hass, config, add_devices, discovery_info=None): gateway_id = discovery_info['gateway'] api = hass.data[KEY_API][gateway_id] gateway = hass.data[KEY_GATEWAY][gateway_id] - api = hass.data[KEY_API] devices_command = gateway.get_devices() devices_commands = yield from api(devices_command) From fb168b47f21af96cb065813b2c16444b3e659737 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 31 Aug 2017 14:41:55 +0100 Subject: [PATCH 33/43] Fix bugs --- homeassistant/components/light/tradfri.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 61779aadc6a21d..2492869007b77e 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -152,8 +152,7 @@ def __init__(self, light, api): self._name = None self._rgb_color = None self._features = SUPPORTED_FEATURES - self._ok_temps = \ - self._light.device_info.manufacturer in ALLOWED_TEMPERATURES + self._temp_supported = False self._refresh(light) @@ -204,7 +203,7 @@ def color_temp(self): """Return the CT color value in mireds.""" if (self._light_data.kelvin_color is None or self.supported_features & SUPPORT_COLOR_TEMP == 0 or - not self._ok_temps): + not self._temp_supported): return None return color_util.color_temperature_kelvin_to_mired( self._light_data.kelvin_color @@ -235,7 +234,8 @@ def async_turn_on(self, **kwargs): color_util.color_rgb_to_hex(*kwargs[ATTR_RGB_COLOR])))) elif ATTR_COLOR_TEMP in kwargs and \ - self._light_data.hex_color is not None and self._ok_temps: + self._light_data.hex_color is not None and \ + self._temp_supported: kelvin = color_util.color_temperature_mired_to_kelvin( kwargs[ATTR_COLOR_TEMP]) self.hass.async_add_job(self._api( @@ -287,8 +287,8 @@ def _refresh(self, light): else: self._features |= SUPPORT_RGB_COLOR - self._ok_temps = ALLOWED_TEMPERATURES.get( - self._light.device_info.manufacturer) + self._temp_supported = self._light.device_info.manufacturer \ + in ALLOWED_TEMPERATURES def _observe_update(self, tradfri_device): """Receive new state data for this light.""" From 4197a911179dd2a1f990a98765811c32a8f46b01 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 31 Aug 2017 15:27:37 +0100 Subject: [PATCH 34/43] Lint --- homeassistant/components/light/tradfri.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 2492869007b77e..c21a558688f8a7 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -288,7 +288,7 @@ def _refresh(self, light): self._features |= SUPPORT_RGB_COLOR self._temp_supported = self._light.device_info.manufacturer \ - in ALLOWED_TEMPERATURES + in ALLOWED_TEMPERATURES def _observe_update(self, tradfri_device): """Receive new state data for this light.""" From 0b33ebc5e58f841b0c94a64ecef72ee85166c183 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Fri, 1 Sep 2017 11:50:28 +0100 Subject: [PATCH 35/43] Add sensor --- homeassistant/components/sensor/tradfri.py | 104 +++++++++++++++++++++ homeassistant/components/tradfri.py | 2 + 2 files changed, 106 insertions(+) create mode 100644 homeassistant/components/sensor/tradfri.py diff --git a/homeassistant/components/sensor/tradfri.py b/homeassistant/components/sensor/tradfri.py new file mode 100644 index 00000000000000..3d5e5798af1840 --- /dev/null +++ b/homeassistant/components/sensor/tradfri.py @@ -0,0 +1,104 @@ +""" +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 logging + +from homeassistant.components.tradfri import ( + KEY_GATEWAY, KEY_TRADFRI_GROUPS, KEY_API) +from homeassistant.util import color as color_util +from homeassistant.helpers.entity import Entity + +_LOGGER = logging.getLogger(__name__) + +DEPENDENCIES = ['tradfri'] + +SCAN_INTERVAL = timedelta(minutes=5) + + +@asyncio.coroutine +def async_setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the IKEA Tradfri device platform.""" + if discovery_info is None: + return + + gateway_id = discovery_info['gateway'] + api = hass.data[KEY_API][gateway_id] + 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) + add_devices(TradfriDevice(device, api) for device in devices) + + +class TradfriDevice(Entity): + """The platform class required by Home Asisstant.""" + + def __init__(self, device, api): + """Initialize the device.""" + self._api = api + self._device = None + self._name = None + + self._refresh(device) + + @asyncio.coroutine + def async_added_to_hass(self): + """Start thread when added to hass.""" + self._async_start_observe() + + @property + def should_poll(self): + """No polling needed for tradfri.""" + return False + + @property + def name(self): + """Return the display name of this device.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit_of_measurement of the device.""" + return '%' + + @property + def device_state_attributes(self): + """Return the devices' state attributes.""" + return dir(self._device.device_info) + + @property + def state(self): + """Return the current state of the device.""" + return self._device.device_info.battery_level + + @callback + def _async_start_observe(self, exc=None): + """Start observation of light.""" + from pytradfri.error import PyTradFriError + if exc: + _LOGGER.warning("Observation failed for %s", self._name, + exc_info=exc) + + try: + cmd = self._device.observe(callback=self._observe_update, + err_callback=self._async_start_observe, + duration=0) + self.hass.async_add_job(self._api(cmd)) + except PyTradFriError as err: + _LOGGER.warning("Observation failed, trying again", exc_info=err) + self._async_start_observe() + + def _refresh(self, device): + """Refresh the device data.""" + self._device = device + self._name = device.name + + def _observe_update(self, tradfri_device): + """Receive new state data for this device.""" + self._refresh(tradfri_device) + + self.hass.async_add_job(self.async_update_ha_state()) diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 3843767485943e..f74046ea5f949b 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -142,6 +142,8 @@ def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): gateways[gateway_id] = gateway hass.async_add_job(discovery.async_load_platform( hass, 'light', DOMAIN, {'gateway': gateway_id}, hass_config)) + hass.async_add_job(discovery.async_load_platform( + hass, 'sensor', DOMAIN, {'gateway': gateway_id}, hass_config)) return True From 98f4cc1b936369200249eb08a7ea1ad07dff0235 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Fri, 1 Sep 2017 11:54:57 +0100 Subject: [PATCH 36/43] Add sensor --- homeassistant/components/sensor/tradfri.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/homeassistant/components/sensor/tradfri.py b/homeassistant/components/sensor/tradfri.py index 3d5e5798af1840..aa24ecce96a118 100644 --- a/homeassistant/components/sensor/tradfri.py +++ b/homeassistant/components/sensor/tradfri.py @@ -4,8 +4,11 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.tradfri/ """ +import asyncio +from datetime import timedelta import logging +from homeassistant.core import callback from homeassistant.components.tradfri import ( KEY_GATEWAY, KEY_TRADFRI_GROUPS, KEY_API) from homeassistant.util import color as color_util From cc327a0b661641082491497c4746c7b5f6678900 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Fri, 1 Sep 2017 12:20:17 +0100 Subject: [PATCH 37/43] Move sensor attrs --- homeassistant/components/light/tradfri.py | 14 ++++++++++++++ homeassistant/components/sensor/tradfri.py | 11 ++++++++++- homeassistant/components/tradfri.py | 2 -- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index c21a558688f8a7..df879050cab203 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -168,6 +168,20 @@ def max_mireds(self): from pytradfri.color import MIN_KELVIN_WS return color_util.color_temperature_kelvin_to_mired(MIN_KELVIN_WS) + @property + def device_state_attributes(self): + """Return the devices' state attributes.""" + info = self._light.device_info + attrs = { + 'manufacturer': info.manufacturer, + 'model_number': info.model_number, + 'serial': info.serial, + 'firmware_version': info.firmware_version, + 'power_source': info.power_source_str, + 'battery_level': info.battery_level + } + return attrs + @asyncio.coroutine def async_added_to_hass(self): """Start thread when added to hass.""" diff --git a/homeassistant/components/sensor/tradfri.py b/homeassistant/components/sensor/tradfri.py index aa24ecce96a118..e4d896aa0506f9 100644 --- a/homeassistant/components/sensor/tradfri.py +++ b/homeassistant/components/sensor/tradfri.py @@ -71,7 +71,16 @@ def unit_of_measurement(self): @property def device_state_attributes(self): """Return the devices' state attributes.""" - return dir(self._device.device_info) + info = self._device.device_info + attrs = { + 'manufacturer': info.manufacturer, + 'model_number': info.model_number, + 'serial': info.serial, + 'firmware_version': info.firmware_version, + 'power_source': info.power_source_str, + 'battery_level': info.battery_level + } + return attrs @property def state(self): diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index f74046ea5f949b..3843767485943e 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -142,8 +142,6 @@ def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): gateways[gateway_id] = gateway hass.async_add_job(discovery.async_load_platform( hass, 'light', DOMAIN, {'gateway': gateway_id}, hass_config)) - hass.async_add_job(discovery.async_load_platform( - hass, 'sensor', DOMAIN, {'gateway': gateway_id}, hass_config)) return True From 152f2797c95303d97b5db948aad5c156341cbff6 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Fri, 1 Sep 2017 12:24:59 +0100 Subject: [PATCH 38/43] Filter devices better --- homeassistant/components/sensor/tradfri.py | 8 +++++--- homeassistant/components/tradfri.py | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/tradfri.py b/homeassistant/components/sensor/tradfri.py index e4d896aa0506f9..08ae3d9ab48323 100644 --- a/homeassistant/components/sensor/tradfri.py +++ b/homeassistant/components/sensor/tradfri.py @@ -5,9 +5,10 @@ https://home-assistant.io/components/sensor.tradfri/ """ import asyncio -from datetime import timedelta import logging +from datetime import timedelta + from homeassistant.core import callback from homeassistant.components.tradfri import ( KEY_GATEWAY, KEY_TRADFRI_GROUPS, KEY_API) @@ -33,12 +34,13 @@ def async_setup_platform(hass, config, add_devices, discovery_info=None): devices_command = gateway.get_devices() devices_commands = yield from api(devices_command) - devices = yield from api(*devices_commands) + all_devices = yield from api(*devices_commands) + devices = [dev for dev in all_devices if not dev.has_light_control] add_devices(TradfriDevice(device, api) for device in devices) class TradfriDevice(Entity): - """The platform class required by Home Asisstant.""" + """The platform class required by Home Assistant.""" def __init__(self, device, api): """Initialize the device.""" diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index 3843767485943e..f74046ea5f949b 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -142,6 +142,8 @@ def _setup_gateway(hass, hass_config, host, key, allow_tradfri_groups): gateways[gateway_id] = gateway hass.async_add_job(discovery.async_load_platform( hass, 'light', DOMAIN, {'gateway': gateway_id}, hass_config)) + hass.async_add_job(discovery.async_load_platform( + hass, 'sensor', DOMAIN, {'gateway': gateway_id}, hass_config)) return True From 06d3e72b2e74e7a933f535c8304615e906dcd163 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Fri, 1 Sep 2017 13:13:14 +0100 Subject: [PATCH 39/43] Lint --- homeassistant/components/sensor/tradfri.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/tradfri.py b/homeassistant/components/sensor/tradfri.py index 08ae3d9ab48323..07f681f7a76e06 100644 --- a/homeassistant/components/sensor/tradfri.py +++ b/homeassistant/components/sensor/tradfri.py @@ -10,9 +10,7 @@ from datetime import timedelta from homeassistant.core import callback -from homeassistant.components.tradfri import ( - KEY_GATEWAY, KEY_TRADFRI_GROUPS, KEY_API) -from homeassistant.util import color as color_util +from homeassistant.components.tradfri import KEY_GATEWAY, KEY_API from homeassistant.helpers.entity import Entity _LOGGER = logging.getLogger(__name__) From e86ea2158bc4a13206fabf3a61ded6048f6f98e7 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 21 Sep 2017 18:42:05 +0100 Subject: [PATCH 40/43] Address comments --- homeassistant/components/light/tradfri.py | 6 +++--- homeassistant/components/sensor/tradfri.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 690f2b6d9623b4..3e466f73e791ed 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -29,7 +29,7 @@ @asyncio.coroutine -def async_setup_platform(hass, config, add_devices, discovery_info=None): +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 @@ -42,14 +42,14 @@ def async_setup_platform(hass, config, add_devices, discovery_info=None): devices_commands = yield from api(devices_command) devices = yield from api(*devices_commands) lights = [dev for dev in devices if dev.has_light_control] - add_devices(TradfriLight(light, api) for light in lights) + async_add_devices(TradfriLight(light, api) for light in lights) 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) - add_devices(TradfriGroup(group, api) for group in groups) + async_add_devices(TradfriGroup(group, api) for group in groups) class TradfriGroup(Light): diff --git a/homeassistant/components/sensor/tradfri.py b/homeassistant/components/sensor/tradfri.py index 07f681f7a76e06..314c18b76369e9 100644 --- a/homeassistant/components/sensor/tradfri.py +++ b/homeassistant/components/sensor/tradfri.py @@ -21,7 +21,7 @@ @asyncio.coroutine -def async_setup_platform(hass, config, add_devices, discovery_info=None): +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 @@ -34,7 +34,7 @@ def async_setup_platform(hass, config, add_devices, discovery_info=None): devices_commands = yield from api(devices_command) all_devices = yield from api(*devices_commands) devices = [dev for dev in all_devices if not dev.has_light_control] - add_devices(TradfriDevice(device, api) for device in devices) + async_add_devices(TradfriDevice(device, api) for device in devices) class TradfriDevice(Entity): From 3eba9aa14e75288c0765a4e051b7c0e58b2bf3ed Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sat, 30 Sep 2017 10:03:49 +0100 Subject: [PATCH 41/43] Pin aiocoap --- virtualization/Docker/scripts/aiocoap | 1 + 1 file changed, 1 insertion(+) diff --git a/virtualization/Docker/scripts/aiocoap b/virtualization/Docker/scripts/aiocoap index 1828643d3cc75d..8e36c616cb442c 100755 --- a/virtualization/Docker/scripts/aiocoap +++ b/virtualization/Docker/scripts/aiocoap @@ -19,4 +19,5 @@ python3 setup.py install cd ../.. git clone --depth 1 https://github.com/chrysn/aiocoap/ cd aiocoap +git reset --hard 0df6a1e44582de99ae944b6a7536d08e2a612e8f python3 -m pip install . From bc589c8fbadbb696ee34c28749653be9bdf83684 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sun, 1 Oct 2017 13:38:31 +0100 Subject: [PATCH 42/43] Fix bug if no devices --- homeassistant/components/light/tradfri.py | 6 ++++-- homeassistant/components/tradfri.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/light/tradfri.py b/homeassistant/components/light/tradfri.py index 3e466f73e791ed..3efab8309fc768 100644 --- a/homeassistant/components/light/tradfri.py +++ b/homeassistant/components/light/tradfri.py @@ -42,14 +42,16 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): devices_commands = yield from api(devices_command) devices = yield from api(*devices_commands) lights = [dev for dev in devices if dev.has_light_control] - async_add_devices(TradfriLight(light, api) for light in lights) + if lights: + async_add_devices(TradfriLight(light, api) for light in lights) 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) - async_add_devices(TradfriGroup(group, api) for group in groups) + if groups: + async_add_devices(TradfriGroup(group, api) for group in groups) class TradfriGroup(Light): diff --git a/homeassistant/components/tradfri.py b/homeassistant/components/tradfri.py index f74046ea5f949b..ef4d7fceed8764 100644 --- a/homeassistant/components/tradfri.py +++ b/homeassistant/components/tradfri.py @@ -16,7 +16,7 @@ from homeassistant.const import CONF_HOST, CONF_API_KEY from homeassistant.components.discovery import SERVICE_IKEA_TRADFRI -REQUIREMENTS = ['pytradfri==2.2'] +REQUIREMENTS = ['pytradfri==2.2.2'] DOMAIN = 'tradfri' CONFIG_FILE = 'tradfri.conf' From f77fd094ac205de31e2068793d179f33ef7727ab Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sun, 1 Oct 2017 13:45:42 +0100 Subject: [PATCH 43/43] Requirements --- requirements_all.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_all.txt b/requirements_all.txt index 966c7432302e51..ac8e7b4ebdba15 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -826,7 +826,7 @@ pythonegardia==1.0.20 pytrackr==0.0.5 # homeassistant.components.tradfri -pytradfri==2.2 +pytradfri==2.2.2 # homeassistant.components.device_tracker.unifi pyunifi==2.13