diff --git a/homeassistant/components/binary_sensor/deconz.py b/homeassistant/components/binary_sensor/deconz.py index 8fea7891c3d..28e78db90ec 100644 --- a/homeassistant/components/binary_sensor/deconz.py +++ b/homeassistant/components/binary_sensor/deconz.py @@ -99,6 +99,6 @@ class DeconzBinarySensor(BinarySensorDevice): attr = { ATTR_BATTERY_LEVEL: self._sensor.battery, } - if self._sensor.type == PRESENCE: + if self._sensor.type in PRESENCE: attr['dark'] = self._sensor.dark return attr diff --git a/homeassistant/components/coinbase.py b/homeassistant/components/coinbase.py index 10123752c99..515da3e4f54 100644 --- a/homeassistant/components/coinbase.py +++ b/homeassistant/components/coinbase.py @@ -14,7 +14,9 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.discovery import load_platform from homeassistant.util import Throttle -REQUIREMENTS = ['coinbase==2.0.7'] +REQUIREMENTS = [ + 'https://github.com/balloob/coinbase-python/archive/' + '3a35efe13ef728a1cc18204b4f25be1fcb1c6006.zip#coinbase==2.0.8a1'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/deconz/__init__.py b/homeassistant/components/deconz/__init__.py index 693f3e4470a..18197b84b61 100644 --- a/homeassistant/components/deconz/__init__.py +++ b/homeassistant/components/deconz/__init__.py @@ -13,6 +13,7 @@ import voluptuous as vol from homeassistant.components.discovery import SERVICE_DECONZ from homeassistant.const import ( CONF_API_KEY, CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP) +from homeassistant.core import callback from homeassistant.helpers import config_validation as cv from homeassistant.helpers import discovery from homeassistant.helpers.aiohttp_client import async_get_clientsession @@ -143,7 +144,18 @@ def async_setup_deconz(hass, config, deconz_config): hass.services.async_register( DOMAIN, 'configure', async_configure, schema=SERVICE_SCHEMA) - hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, deconz.close) + @callback + def deconz_shutdown(event): + """ + Wrap the call to deconz.close. + + Used as an argument to EventBus.async_listen_once - EventBus calls + this method with the event as the first argument, which should not + be passed on to deconz.close. + """ + deconz.close() + + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, deconz_shutdown) return True diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 2a9a7a8a38a..3863a4d390b 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -23,7 +23,7 @@ from homeassistant.const import CONF_NAME, EVENT_THEMES_UPDATED from homeassistant.core import callback from homeassistant.loader import bind_hass -REQUIREMENTS = ['home-assistant-frontend==20180221.1', 'user-agents==1.1.0'] +REQUIREMENTS = ['home-assistant-frontend==20180227.0', 'user-agents==1.1.0'] DOMAIN = 'frontend' DEPENDENCIES = ['api', 'websocket_api', 'http', 'system_log'] diff --git a/homeassistant/components/light/iglo.py b/homeassistant/components/light/iglo.py index e39b5dbf540..1e110b5c397 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.5'] +REQUIREMENTS = ['iglo==1.2.6'] _LOGGER = logging.getLogger(__name__) @@ -56,13 +56,13 @@ class IGloLamp(Light): @property def brightness(self): """Return the brightness of this light between 0..255.""" - return int((self._lamp.state['brightness'] / 200.0) * 255) + return int((self._lamp.state()['brightness'] / 200.0) * 255) @property def color_temp(self): """Return the color temperature.""" return color_util.color_temperature_kelvin_to_mired( - self._lamp.state['white']) + self._lamp.state()['white']) @property def min_mireds(self): @@ -79,12 +79,12 @@ class IGloLamp(Light): @property def rgb_color(self): """Return the RGB value.""" - return self._lamp.state['rgb'] + return self._lamp.state()['rgb'] @property def effect(self): """Return the current effect.""" - return self._lamp.state['effect'] + return self._lamp.state()['effect'] @property def effect_list(self): @@ -100,7 +100,7 @@ class IGloLamp(Light): @property def is_on(self): """Return true if light is on.""" - return self._lamp.state['on'] + return self._lamp.state()['on'] def turn_on(self, **kwargs): """Turn the light on.""" diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index 40e09ea328c..d3cf2f7b501 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -8,9 +8,11 @@ https://home-assistant.io/components/media_player.cast/ import asyncio import logging import threading +import functools import voluptuous as vol +from homeassistant.exceptions import PlatformNotReady from homeassistant.helpers.typing import HomeAssistantType, ConfigType from homeassistant.core import callback from homeassistant.helpers.dispatcher import (dispatcher_send, @@ -34,6 +36,7 @@ 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 | \ @@ -76,7 +79,7 @@ def _setup_internal_discovery(hass: HomeAssistantType) -> None: try: # pylint: disable=protected-access chromecast = pychromecast._get_chromecast_from_host( - mdns, blocking=True) + mdns, blocking=True, tries=SOCKET_CLIENT_RETRIES) except pychromecast.ChromecastConnectionError: _LOGGER.debug("Can't set up cast with mDNS info %s. " "Assuming it's not a Chromecast", mdns) @@ -182,11 +185,13 @@ def async_setup_platform(hass: HomeAssistantType, config: ConfigType, else: # Manually add a "normal" Chromecast, we can do that without discovery. try: - chromecast = yield from hass.async_add_job( - pychromecast.Chromecast, *want_host) - except pychromecast.ChromecastConnectionError: - _LOGGER.warning("Can't set up chromecast on %s", want_host[0]) - raise + func = functools.partial(pychromecast.Chromecast, *want_host, + tries=SOCKET_CLIENT_RETRIES) + chromecast = yield from hass.async_add_job(func) + except pychromecast.ChromecastConnectionError as err: + _LOGGER.warning("Can't set up chromecast on %s: %s", + want_host[0], err) + raise PlatformNotReady key = (chromecast.host, chromecast.port, chromecast.uuid) cast_device = _async_create_cast_device(hass, chromecast) if cast_device is not None: diff --git a/homeassistant/components/media_player/denonavr.py b/homeassistant/components/media_player/denonavr.py index 5bc16d11d64..fe8fc46c24b 100644 --- a/homeassistant/components/media_player/denonavr.py +++ b/homeassistant/components/media_player/denonavr.py @@ -20,7 +20,7 @@ from homeassistant.const import ( CONF_NAME, STATE_ON, CONF_ZONE, CONF_TIMEOUT) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['denonavr==0.6.0'] +REQUIREMENTS = ['denonavr==0.6.1'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 0485d82a274..8a5fdb5b86b 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -588,7 +588,7 @@ class MQTT(object): def _mqtt_on_message(self, _mqttc, _userdata, msg): """Message received callback.""" - self.hass.async_add_job(self._mqtt_handle_message, msg) + self.hass.add_job(self._mqtt_handle_message, msg) @callback def _mqtt_handle_message(self, msg): diff --git a/homeassistant/components/mysensors.py b/homeassistant/components/mysensors.py index 390da7ed0e0..37e257e5eb9 100644 --- a/homeassistant/components/mysensors.py +++ b/homeassistant/components/mysensors.py @@ -152,10 +152,8 @@ CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_BAUD_RATE, default=DEFAULT_BAUD_RATE): cv.positive_int, vol.Optional(CONF_TCP_PORT, default=DEFAULT_TCP_PORT): cv.port, - vol.Optional(CONF_TOPIC_IN_PREFIX, default=''): - valid_subscribe_topic, - vol.Optional(CONF_TOPIC_OUT_PREFIX, default=''): - valid_publish_topic, + vol.Optional(CONF_TOPIC_IN_PREFIX): valid_subscribe_topic, + vol.Optional(CONF_TOPIC_OUT_PREFIX): valid_publish_topic, vol.Optional(CONF_NODES, default={}): NODE_SCHEMA, }] ), @@ -358,8 +356,8 @@ def setup(hass, config): hass.config.path('mysensors{}.pickle'.format(index + 1))) baud_rate = gway.get(CONF_BAUD_RATE) tcp_port = gway.get(CONF_TCP_PORT) - in_prefix = gway.get(CONF_TOPIC_IN_PREFIX) - out_prefix = gway.get(CONF_TOPIC_OUT_PREFIX) + in_prefix = gway.get(CONF_TOPIC_IN_PREFIX, '') + out_prefix = gway.get(CONF_TOPIC_OUT_PREFIX, '') ready_gateway = setup_gateway( device, persistence_file, baud_rate, tcp_port, in_prefix, out_prefix) diff --git a/homeassistant/components/remote/harmony.py b/homeassistant/components/remote/harmony.py index 25a1a684d3c..842dce087e8 100644 --- a/homeassistant/components/remote/harmony.py +++ b/homeassistant/components/remote/harmony.py @@ -31,7 +31,7 @@ CONF_DEVICE_CACHE = 'harmony_device_cache' SERVICE_SYNC = 'harmony_sync' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(ATTR_ACTIVITY): cv.string, + vol.Optional(ATTR_ACTIVITY): cv.string, vol.Required(CONF_NAME): cv.string, vol.Optional(ATTR_DELAY_SECS, default=DEFAULT_DELAY_SECS): vol.Coerce(float), @@ -71,7 +71,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): port) # Ignore hub name when checking if this hub is known - ip and port only - if host and host[1:] in (h.host for h in DEVICES): + if host[1:] in ((h.host, h.port) for h in DEVICES): _LOGGER.debug("Discovered host already known: %s", host) return elif CONF_HOST in config: @@ -139,7 +139,7 @@ class HarmonyRemote(remote.RemoteDevice): _LOGGER.debug("HarmonyRemote device init started for: %s", name) self._name = name self.host = host - self._port = port + self.port = port self._state = None self._current_activity = None self._default_activity = activity diff --git a/homeassistant/components/sensor/alpha_vantage.py b/homeassistant/components/sensor/alpha_vantage.py index 81c84a7f918..896497a93d5 100644 --- a/homeassistant/components/sensor/alpha_vantage.py +++ b/homeassistant/components/sensor/alpha_vantage.py @@ -70,8 +70,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): from alpha_vantage.foreignexchange import ForeignExchange api_key = config.get(CONF_API_KEY) - symbols = config.get(CONF_SYMBOLS) - conversions = config.get(CONF_FOREIGN_EXCHANGE) + symbols = config.get(CONF_SYMBOLS, []) + conversions = config.get(CONF_FOREIGN_EXCHANGE, []) if not symbols and not conversions: msg = 'Warning: No symbols or currencies configured.' diff --git a/homeassistant/components/sensor/broadlink.py b/homeassistant/components/sensor/broadlink.py index 1440e2496fe..47cefe50aec 100644 --- a/homeassistant/components/sensor/broadlink.py +++ b/homeassistant/components/sensor/broadlink.py @@ -19,7 +19,9 @@ from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['broadlink==0.5'] +REQUIREMENTS = [ + 'https://github.com/balloob/python-broadlink/archive/' + '3580ff2eaccd267846f14246d6ede6e30671f7c6.zip#broadlink==0.5.1'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/switch/broadlink.py b/homeassistant/components/switch/broadlink.py index 91ecc9c7111..38888733ba6 100644 --- a/homeassistant/components/switch/broadlink.py +++ b/homeassistant/components/switch/broadlink.py @@ -22,7 +22,9 @@ import homeassistant.helpers.config_validation as cv from homeassistant.util import Throttle from homeassistant.util.dt import utcnow -REQUIREMENTS = ['broadlink==0.5'] +REQUIREMENTS = [ + 'https://github.com/balloob/python-broadlink/archive/' + '3580ff2eaccd267846f14246d6ede6e30671f7c6.zip#broadlink==0.5.1'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/tahoma.py b/homeassistant/components/tahoma.py index b288a704d74..7c8d047fbcf 100644 --- a/homeassistant/components/tahoma.py +++ b/homeassistant/components/tahoma.py @@ -14,7 +14,7 @@ from homeassistant.helpers import discovery from homeassistant.helpers import config_validation as cv from homeassistant.helpers.entity import Entity -REQUIREMENTS = ['tahoma-api==0.0.12'] +REQUIREMENTS = ['tahoma-api==0.0.13'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/vacuum/roomba.py b/homeassistant/components/vacuum/roomba.py index 6485f0025e2..b983b20bd0c 100644 --- a/homeassistant/components/vacuum/roomba.py +++ b/homeassistant/components/vacuum/roomba.py @@ -8,12 +8,15 @@ import asyncio import logging import voluptuous as vol +import async_timeout + from homeassistant.components.vacuum import ( VacuumDevice, PLATFORM_SCHEMA, SUPPORT_BATTERY, SUPPORT_FAN_SPEED, SUPPORT_PAUSE, SUPPORT_RETURN_HOME, SUPPORT_SEND_COMMAND, SUPPORT_STATUS, SUPPORT_STOP, SUPPORT_TURN_OFF, SUPPORT_TURN_ON) from homeassistant.const import ( CONF_HOST, CONF_NAME, CONF_PASSWORD, CONF_USERNAME) +from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv @@ -90,7 +93,13 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): ) _LOGGER.info("Initializing communication with host %s (username: %s)", host, username) - yield from hass.async_add_job(roomba.connect) + + try: + with async_timeout.timeout(9): + yield from hass.async_add_job(roomba.connect) + except asyncio.TimeoutError: + raise PlatformNotReady + roomba_vac = RoombaVacuum(name, roomba) hass.data[PLATFORM][host] = roomba_vac diff --git a/homeassistant/components/weather/darksky.py b/homeassistant/components/weather/darksky.py index 21f67ce080a..139f8abfce6 100644 --- a/homeassistant/components/weather/darksky.py +++ b/homeassistant/components/weather/darksky.py @@ -96,7 +96,7 @@ class DarkSkyWeather(WeatherEntity): @property def humidity(self): """Return the humidity.""" - return self._ds_currently.get('humidity') * 100.0 + return round(self._ds_currently.get('humidity') * 100.0, 2) @property def wind_speed(self): diff --git a/homeassistant/components/zha/__init__.py b/homeassistant/components/zha/__init__.py index bb29cb28b0f..9a8c88e6f23 100644 --- a/homeassistant/components/zha/__init__.py +++ b/homeassistant/components/zha/__init__.py @@ -17,8 +17,8 @@ from homeassistant.helpers import discovery, entity from homeassistant.util import slugify REQUIREMENTS = [ - 'bellows==0.5.0', - 'zigpy==0.0.1', + 'bellows==0.5.1', + 'zigpy==0.0.3', 'zigpy-xbee==0.0.2', ] diff --git a/homeassistant/const.py b/homeassistant/const.py index a067e14d344..82ebadd80f4 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 64 -PATCH_VERSION = '0' +PATCH_VERSION = '1' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 2eb42b94389..7b6a5f09330 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -15,3 +15,6 @@ attrs==17.4.0 # Breaks Python 3.6 and is not needed for our supported Python versions enum34==1000000000.0.0 + +# This is a old unmaintained library and is replaced with pycryptodome +pycrypto==1000000000.0.0 diff --git a/requirements_all.txt b/requirements_all.txt index 7deac085466..88d8d19e1c8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -133,7 +133,7 @@ batinfo==0.4.2 beautifulsoup4==4.6.0 # homeassistant.components.zha -bellows==0.5.0 +bellows==0.5.1 # homeassistant.components.bmw_connected_drive bimmer_connected==0.3.0 @@ -165,10 +165,6 @@ boto3==1.4.7 # homeassistant.scripts.credstash botocore==1.7.34 -# homeassistant.components.sensor.broadlink -# homeassistant.components.switch.broadlink -broadlink==0.5 - # homeassistant.components.sensor.buienradar # homeassistant.components.weather.buienradar buienradar==0.91 @@ -179,9 +175,6 @@ caldav==0.5.0 # homeassistant.components.notify.ciscospark ciscosparkapi==0.4.2 -# homeassistant.components.coinbase -coinbase==2.0.7 - # homeassistant.components.sensor.coinmarketcap coinmarketcap==4.2.1 @@ -219,7 +212,7 @@ defusedxml==0.5.0 deluge-client==1.0.5 # homeassistant.components.media_player.denonavr -denonavr==0.6.0 +denonavr==0.6.1 # homeassistant.components.media_player.directv directpy==0.2 @@ -356,7 +349,7 @@ hipnotify==1.0.8 holidays==0.9.3 # homeassistant.components.frontend -home-assistant-frontend==20180221.1 +home-assistant-frontend==20180227.0 # homeassistant.components.camera.onvif http://github.com/tgaugry/suds-passworddigest-py3/archive/86fc50e39b4d2b8997481967d6a7fe1c57118999.zip#suds-passworddigest-py3==0.1.2a @@ -370,6 +363,13 @@ httplib2==0.10.3 # homeassistant.components.media_player.braviatv https://github.com/aparraga/braviarc/archive/0.3.7.zip#braviarc==0.3.7 +# homeassistant.components.coinbase +https://github.com/balloob/coinbase-python/archive/3a35efe13ef728a1cc18204b4f25be1fcb1c6006.zip#coinbase==2.0.8a1 + +# homeassistant.components.sensor.broadlink +# homeassistant.components.switch.broadlink +https://github.com/balloob/python-broadlink/archive/3580ff2eaccd267846f14246d6ede6e30671f7c6.zip#broadlink==0.5.1 + # homeassistant.components.media_player.spotify https://github.com/happyleavesaoc/spotipy/archive/544614f4b1d508201d363e84e871f86c90aa26b2.zip#spotipy==2.4.4 @@ -400,7 +400,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.5 +iglo==1.2.6 # homeassistant.components.ihc ihcsdk==2.1.1 @@ -1156,7 +1156,7 @@ steamodd==4.21 suds-py3==1.3.3.0 # homeassistant.components.tahoma -tahoma-api==0.0.12 +tahoma-api==0.0.13 # homeassistant.components.sensor.tank_utility tank_utility==1.4.0 @@ -1298,4 +1298,4 @@ ziggo-mediabox-xl==1.0.0 zigpy-xbee==0.0.2 # homeassistant.components.zha -zigpy==0.0.1 +zigpy==0.0.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1e443e3ad00..9fa6e7f5cde 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -75,7 +75,7 @@ hbmqtt==0.9.1 holidays==0.9.3 # homeassistant.components.frontend -home-assistant-frontend==20180221.1 +home-assistant-frontend==20180227.0 # homeassistant.components.influxdb # homeassistant.components.sensor.influxdb diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 460c998f556..31e0635e411 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -113,6 +113,9 @@ CONSTRAINT_PATH = os.path.join(os.path.dirname(__file__), CONSTRAINT_BASE = """ # Breaks Python 3.6 and is not needed for our supported Python versions enum34==1000000000.0.0 + +# This is a old unmaintained library and is replaced with pycryptodome +pycrypto==1000000000.0.0 """ diff --git a/tests/components/media_player/test_cast.py b/tests/components/media_player/test_cast.py index 6eeb9136b07..aaaad47d8dc 100644 --- a/tests/components/media_player/test_cast.py +++ b/tests/components/media_player/test_cast.py @@ -7,6 +7,7 @@ from uuid import UUID import pytest +from homeassistant.exceptions import PlatformNotReady from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.components.media_player import cast @@ -122,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) + gen_chromecast.assert_called_once_with(mdns, blocking=True, tries=10) discover_cast('the-service', chromecast) gen_chromecast.reset_mock() @@ -196,6 +197,10 @@ def test_create_cast_device_with_uuid(hass): @asyncio.coroutine def test_normal_chromecast_not_starting_discovery(hass): """Test cast platform not starting discovery when not required.""" + import pychromecast # imports mock pychromecast + + pychromecast.ChromecastConnectionError = IOError + chromecast = get_fake_chromecast() with patch('pychromecast.Chromecast', return_value=chromecast): @@ -216,6 +221,11 @@ def test_normal_chromecast_not_starting_discovery(hass): hass, discovery_info={'host': 'host1', 'port': 42}) assert add_devices.call_count == 0 + with patch('pychromecast.Chromecast', + side_effect=pychromecast.ChromecastConnectionError): + with pytest.raises(PlatformNotReady): + yield from async_setup_cast(hass, {'host': 'host3'}) + @asyncio.coroutine def test_replay_past_chromecasts(hass):