From e6683b4c849f960487c80d4b142dbe161d61b10d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Mar 2018 12:51:40 -0700 Subject: [PATCH 01/11] Bump version to 0.65.3 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 2fee845f70a..203a9c63d95 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 65 -PATCH_VERSION = '2' +PATCH_VERSION = '3' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 5, 3) From a7f34bbce9e564e648751e9cc8e9896887741745 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Mar 2018 09:49:28 -0700 Subject: [PATCH 02/11] Implement Hue available property (#12939) --- homeassistant/components/light/hue.py | 11 ++++--- tests/components/light/test_hue.py | 42 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/light/hue.py b/homeassistant/components/light/hue.py index bee6840f346..75825683928 100644 --- a/homeassistant/components/light/hue.py +++ b/homeassistant/components/light/hue.py @@ -261,10 +261,13 @@ class HueLight(Light): """Return true if device is on.""" if self.is_group: return self.info['state']['any_on'] - elif self.allow_unreachable: - return self.info['state']['on'] - return self.info['state']['reachable'] and \ - self.info['state']['on'] + return self.info['state']['on'] + + @property + def available(self): + """Return if light is available.""" + return (self.is_group or self.allow_unreachable or + self.info['state']['reachable']) @property def supported_features(self): diff --git a/tests/components/light/test_hue.py b/tests/components/light/test_hue.py index 5c28ea9988f..559467d5e9a 100644 --- a/tests/components/light/test_hue.py +++ b/tests/components/light/test_hue.py @@ -501,3 +501,45 @@ class TestHueLight(unittest.TestCase): light = self.buildLight(info={}, is_group=True) self.assertIsNone(light.unique_id) + + +def test_available(): + """Test available property.""" + light = hue_light.HueLight( + info={'state': {'reachable': False}}, + allow_unreachable=False, + is_group=False, + + light_id=None, + bridge=mock.Mock(), + update_lights_cb=None, + allow_in_emulated_hue=False, + ) + + assert light.available is False + + light = hue_light.HueLight( + info={'state': {'reachable': False}}, + allow_unreachable=True, + is_group=False, + + light_id=None, + bridge=mock.Mock(), + update_lights_cb=None, + allow_in_emulated_hue=False, + ) + + assert light.available is True + + light = hue_light.HueLight( + info={'state': {'reachable': False}}, + allow_unreachable=False, + is_group=True, + + light_id=None, + bridge=mock.Mock(), + update_lights_cb=None, + allow_in_emulated_hue=False, + ) + + assert light.available is True From 7018806802e8905b51d000c93bce3e379eb240af Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Mar 2018 12:32:12 -0700 Subject: [PATCH 03/11] Run asyncio event loop in debug mode during tests (#13058) * Run asyncio event loop in debug mode during tests * Remove debug mode again --- homeassistant/components/camera/arlo.py | 5 ++--- homeassistant/components/climate/generic_thermostat.py | 2 +- tests/components/cover/test_template.py | 4 ++-- tests/components/zwave/test_init.py | 4 ++-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/camera/arlo.py b/homeassistant/components/camera/arlo.py index 4d461b0e0b5..f3e70c2bdd7 100644 --- a/homeassistant/components/camera/arlo.py +++ b/homeassistant/components/camera/arlo.py @@ -49,8 +49,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ }) -@asyncio.coroutine -def async_setup_platform(hass, config, async_add_devices, discovery_info=None): +def setup_platform(hass, config, add_devices, discovery_info=None): """Set up an Arlo IP Camera.""" arlo = hass.data.get(DATA_ARLO) if not arlo: @@ -60,7 +59,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): for camera in arlo.cameras: cameras.append(ArloCam(hass, camera, config)) - async_add_devices(cameras, True) + add_devices(cameras, True) class ArloCam(Camera): diff --git a/homeassistant/components/climate/generic_thermostat.py b/homeassistant/components/climate/generic_thermostat.py index b97dc221298..b5d3c3f7c25 100644 --- a/homeassistant/components/climate/generic_thermostat.py +++ b/homeassistant/components/climate/generic_thermostat.py @@ -229,7 +229,7 @@ class GenericThermostat(ClimateDevice): """List of available operation modes.""" return self._operation_list - def set_operation_mode(self, operation_mode): + async def async_set_operation_mode(self, operation_mode): """Set operation mode.""" if operation_mode == STATE_HEAT: self._current_operation = STATE_HEAT diff --git a/tests/components/cover/test_template.py b/tests/components/cover/test_template.py index 3d7aa3ce618..b786b463dad 100644 --- a/tests/components/cover/test_template.py +++ b/tests/components/cover/test_template.py @@ -135,7 +135,7 @@ class TestTemplateCover(unittest.TestCase): entity = self.hass.states.get('cover.test') attrs = dict() attrs['position'] = 42 - self.hass.states.async_set( + self.hass.states.set( entity.entity_id, entity.state, attributes=attrs) self.hass.block_till_done() @@ -148,7 +148,7 @@ class TestTemplateCover(unittest.TestCase): self.hass.block_till_done() entity = self.hass.states.get('cover.test') attrs['position'] = 0.0 - self.hass.states.async_set( + self.hass.states.set( entity.entity_id, entity.state, attributes=attrs) self.hass.block_till_done() diff --git a/tests/components/zwave/test_init.py b/tests/components/zwave/test_init.py index 828385b9ded..527101f6c61 100644 --- a/tests/components/zwave/test_init.py +++ b/tests/components/zwave/test_init.py @@ -309,7 +309,7 @@ def test_value_discovery_existing_entity(hass, mock_openzwave): 'current_temperature'] is None def mock_update(self): - self.hass.async_add_job(self.async_update_ha_state) + self.hass.add_job(self.async_update_ha_state) with patch.object(zwave.node_entity.ZWaveBaseEntity, 'maybe_schedule_update', new=mock_update): @@ -356,7 +356,7 @@ def test_power_schemes(hass, mock_openzwave): 'switch.mock_node_mock_value').attributes def mock_update(self): - self.hass.async_add_job(self.async_update_ha_state) + self.hass.add_job(self.async_update_ha_state) with patch.object(zwave.node_entity.ZWaveBaseEntity, 'maybe_schedule_update', new=mock_update): From 7935c2504eceb2f2a5b81be9dc62b1af00c5a7e3 Mon Sep 17 00:00:00 2001 From: Julius Mittenzwei Date: Sun, 11 Mar 2018 05:26:21 +0100 Subject: [PATCH 04/11] Fixes KNX fire event problem, issue https://github.com/home-assistant/home-assistant/issues/13049 (#13062) --- homeassistant/components/knx.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/knx.py b/homeassistant/components/knx.py index f6f41619ca8..61f8ca90137 100644 --- a/homeassistant/components/knx.py +++ b/homeassistant/components/knx.py @@ -17,7 +17,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.event import async_track_state_change from homeassistant.helpers.script import Script -REQUIREMENTS = ['xknx==0.8.4'] +REQUIREMENTS = ['xknx==0.8.5'] DOMAIN = "knx" DATA_KNX = "data_knx" @@ -241,7 +241,7 @@ class KNXModule(object): async def telegram_received_cb(self, telegram): """Call invoked after a KNX telegram was received.""" self.hass.bus.fire('knx_event', { - 'address': telegram.group_address.str(), + 'address': str(telegram.group_address), 'data': telegram.payload.value }) # False signals XKNX to proceed with processing telegrams. diff --git a/requirements_all.txt b/requirements_all.txt index 03560ac79b0..a3a5662822e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1274,7 +1274,7 @@ xbee-helper==0.0.7 xboxapi==0.1.1 # homeassistant.components.knx -xknx==0.8.4 +xknx==0.8.5 # homeassistant.components.media_player.bluesound # homeassistant.components.sensor.startca From 85fa88c8b334b49fad93383396c12def6b153e7e Mon Sep 17 00:00:00 2001 From: Jesse Hills Date: Sun, 11 Mar 2018 17:31:57 +1300 Subject: [PATCH 05/11] - Bump iGlo Version (#13063) - Use effect list as a method --- homeassistant/components/light/iglo.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/light/iglo.py b/homeassistant/components/light/iglo.py index 1e110b5c397..9717993f77d 100644 --- a/homeassistant/components/light/iglo.py +++ b/homeassistant/components/light/iglo.py @@ -17,7 +17,7 @@ from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT import homeassistant.helpers.config_validation as cv import homeassistant.util.color as color_util -REQUIREMENTS = ['iglo==1.2.6'] +REQUIREMENTS = ['iglo==1.2.7'] _LOGGER = logging.getLogger(__name__) @@ -89,7 +89,7 @@ class IGloLamp(Light): @property def effect_list(self): """Return the list of supported effects.""" - return self._lamp.effect_list + return self._lamp.effect_list() @property def supported_features(self): diff --git a/requirements_all.txt b/requirements_all.txt index a3a5662822e..ad221e0c66a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -398,7 +398,7 @@ https://github.com/wokar/pylgnetcast/archive/v0.2.0.zip#pylgnetcast==0.2.0 # i2csense==0.0.4 # homeassistant.components.light.iglo -iglo==1.2.6 +iglo==1.2.7 # homeassistant.components.ihc ihcsdk==2.2.0 From e37619acc13f0f3e93954c48b2986c92ece452b0 Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Sat, 10 Mar 2018 22:27:58 +0000 Subject: [PATCH 06/11] Convert decimals from SQL results --- homeassistant/components/sensor/sql.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/sql.py b/homeassistant/components/sensor/sql.py index 402076c6fd8..5d5d61ff822 100644 --- a/homeassistant/components/sensor/sql.py +++ b/homeassistant/components/sensor/sql.py @@ -144,7 +144,7 @@ class SQLSensor(Entity): data = res[self._column_name] for key, value in res.items(): if isinstance(value, decimal.Decimal): - value = float(decimal) + value = float(value) self._attributes[key] = value except sqlalchemy.exc.SQLAlchemyError as err: _LOGGER.error("Error executing query %s: %s", self._query, err) From e3d176f479e2df32c727ee8dc9edeb06cb41b60a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Mar 2018 12:33:07 -0700 Subject: [PATCH 07/11] Fix Tado doing async wrong (#13078) * Fix Tado doing async wrong * Remove last coroutine decorator --- .../components/device_tracker/tado.py | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/device_tracker/tado.py b/homeassistant/components/device_tracker/tado.py index dcf06036ea0..11d12322ff5 100644 --- a/homeassistant/components/device_tracker/tado.py +++ b/homeassistant/components/device_tracker/tado.py @@ -68,22 +68,18 @@ class TadoDeviceScanner(DeviceScanner): self.websession = async_create_clientsession( hass, cookie_jar=aiohttp.CookieJar(unsafe=True, loop=hass.loop)) - self.success_init = self._update_info() + self.success_init = asyncio.run_coroutine_threadsafe( + self._async_update_info(), hass.loop + ).result() + _LOGGER.info("Scanner initialized") - @asyncio.coroutine - def async_scan_devices(self): + async def async_scan_devices(self): """Scan for devices and return a list containing found device ids.""" - info = self._update_info() - - # Don't yield if we got None - if info is not None: - yield from info - + await self._async_update_info() return [device.mac for device in self.last_results] - @asyncio.coroutine - def async_get_device_name(self, device): + async def async_get_device_name(self, device): """Return the name of the given device or None if we don't know.""" filter_named = [result.name for result in self.last_results if result.mac == device] @@ -93,7 +89,7 @@ class TadoDeviceScanner(DeviceScanner): return None @Throttle(MIN_TIME_BETWEEN_SCANS) - def _update_info(self): + async def _async_update_info(self): """ Query Tado for device marked as at home. @@ -111,14 +107,14 @@ class TadoDeviceScanner(DeviceScanner): home_id=self.home_id, username=self.username, password=self.password) - response = yield from self.websession.get(url) + response = await self.websession.get(url) if response.status != 200: _LOGGER.warning( "Error %d on %s.", response.status, self.tadoapiurl) - return + return False - tado_json = yield from response.json() + tado_json = await response.json() except (asyncio.TimeoutError, aiohttp.ClientError): _LOGGER.error("Cannot load Tado data") @@ -139,7 +135,7 @@ class TadoDeviceScanner(DeviceScanner): self.last_results = last_results - _LOGGER.info( + _LOGGER.debug( "Tado presence query successful, %d device(s) at home", len(self.last_results) ) From 8e51c12010b66637e41b38f0b26fba9fa0401353 Mon Sep 17 00:00:00 2001 From: Joe Lu Date: Sun, 11 Mar 2018 13:33:36 -0600 Subject: [PATCH 08/11] Integrated with py-synology:0.2.0 which has fix to auto-renew session when it's expired (#13079) --- homeassistant/components/camera/synology.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/camera/synology.py b/homeassistant/components/camera/synology.py index fca9cbbc7a5..8bbb3e8c632 100644 --- a/homeassistant/components/camera/synology.py +++ b/homeassistant/components/camera/synology.py @@ -20,7 +20,7 @@ from homeassistant.helpers.aiohttp_client import ( async_get_clientsession) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['py-synology==0.1.5'] +REQUIREMENTS = ['py-synology==0.2.0'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index ad221e0c66a..cbbd797db2d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -632,7 +632,7 @@ py-cpuinfo==3.3.0 py-melissa-climate==1.0.6 # homeassistant.components.camera.synology -py-synology==0.1.5 +py-synology==0.2.0 # homeassistant.components.hdmi_cec pyCEC==0.4.13 From a34786fb2dbfedcbaa998ab06282d7e5fe4660b2 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sun, 11 Mar 2018 20:42:58 +0100 Subject: [PATCH 09/11] Revert "Cast automatically drop connection (#12635)" (#13094) This reverts commit e14893416fb98d3ef9a37d816e0ee719105b33a1. --- homeassistant/components/media_player/cast.py | 9 +++------ tests/components/media_player/test_cast.py | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index dbcb53ec185..579f9b62864 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -7,7 +7,6 @@ https://home-assistant.io/components/media_player.cast/ # pylint: disable=import-error import logging import threading -import functools import voluptuous as vol @@ -35,7 +34,6 @@ CONF_IGNORE_CEC = 'ignore_cec' CAST_SPLASH = 'https://home-assistant.io/images/cast/splash.png' DEFAULT_PORT = 8009 -SOCKET_CLIENT_RETRIES = 10 SUPPORT_CAST = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \ SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PREVIOUS_TRACK | \ @@ -78,7 +76,7 @@ def _setup_internal_discovery(hass: HomeAssistantType) -> None: try: # pylint: disable=protected-access chromecast = pychromecast._get_chromecast_from_host( - mdns, blocking=True, tries=SOCKET_CLIENT_RETRIES) + mdns, blocking=True) except pychromecast.ChromecastConnectionError: _LOGGER.debug("Can't set up cast with mDNS info %s. " "Assuming it's not a Chromecast", mdns) @@ -183,9 +181,8 @@ async def async_setup_platform(hass: HomeAssistantType, config: ConfigType, else: # Manually add a "normal" Chromecast, we can do that without discovery. try: - func = functools.partial(pychromecast.Chromecast, *want_host, - tries=SOCKET_CLIENT_RETRIES) - chromecast = await hass.async_add_job(func) + chromecast = await hass.async_add_job( + pychromecast.Chromecast, *want_host) except pychromecast.ChromecastConnectionError as err: _LOGGER.warning("Can't set up chromecast on %s: %s", want_host[0], err) diff --git a/tests/components/media_player/test_cast.py b/tests/components/media_player/test_cast.py index aaaad47d8dc..2075b4cf6e6 100644 --- a/tests/components/media_player/test_cast.py +++ b/tests/components/media_player/test_cast.py @@ -123,7 +123,7 @@ def test_internal_discovery_callback_only_generates_once(hass): return_value=chromecast) as gen_chromecast: discover_cast('the-service', chromecast) mdns = (chromecast.host, chromecast.port, chromecast.uuid, None, None) - gen_chromecast.assert_called_once_with(mdns, blocking=True, tries=10) + gen_chromecast.assert_called_once_with(mdns, blocking=True) discover_cast('the-service', chromecast) gen_chromecast.reset_mock() From 8603f1a047dafe69e0c0ce309ce22646e52b7653 Mon Sep 17 00:00:00 2001 From: Greg Dowling Date: Sun, 11 Mar 2018 19:43:28 +0000 Subject: [PATCH 10/11] Bump pyvera to 0.2.42. Improve event loop robustness. (#13095) --- homeassistant/components/vera.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/vera.py b/homeassistant/components/vera.py index a7c10462e0d..5cc4de0d5ca 100644 --- a/homeassistant/components/vera.py +++ b/homeassistant/components/vera.py @@ -19,7 +19,7 @@ from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP, CONF_LIGHTS, CONF_EXCLUDE) from homeassistant.helpers.entity import Entity -REQUIREMENTS = ['pyvera==0.2.41'] +REQUIREMENTS = ['pyvera==0.2.42'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index cbbd797db2d..300952e061f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1021,7 +1021,7 @@ pyunifi==2.13 # pyuserinput==0.1.11 # homeassistant.components.vera -pyvera==0.2.41 +pyvera==0.2.42 # homeassistant.components.media_player.vizio pyvizio==0.0.2 From 31130f902b36f72d8dcc73c9707d70fa673e33b1 Mon Sep 17 00:00:00 2001 From: tadly Date: Sun, 11 Mar 2018 20:46:16 +0100 Subject: [PATCH 11/11] Updated jsonrpc-websocket to 0.6 (#13096) Fix Kodi by updating jsonrpc-websocket to 0.6 --- homeassistant/components/media_player/kodi.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/media_player/kodi.py b/homeassistant/components/media_player/kodi.py index d14bf0fadaf..6450b2f5b35 100644 --- a/homeassistant/components/media_player/kodi.py +++ b/homeassistant/components/media_player/kodi.py @@ -31,7 +31,7 @@ from homeassistant.helpers import script, config_validation as cv from homeassistant.helpers.template import Template from homeassistant.util.yaml import dump -REQUIREMENTS = ['jsonrpc-async==0.6', 'jsonrpc-websocket==0.5'] +REQUIREMENTS = ['jsonrpc-async==0.6', 'jsonrpc-websocket==0.6'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 300952e061f..cc4e7dbd708 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -421,7 +421,7 @@ jsonpath==0.75 jsonrpc-async==0.6 # homeassistant.components.media_player.kodi -jsonrpc-websocket==0.5 +jsonrpc-websocket==0.6 # homeassistant.scripts.keyring keyring==11.0.0