From 761b4181c01a608cb64231aebf538519730b6497 Mon Sep 17 00:00:00 2001 From: ChristianKuehnel Date: Wed, 28 Feb 2018 03:05:38 +0100 Subject: [PATCH 01/15] updated to bimmer_connected 0.4.1 (#12759) fixes https://github.com/home-assistant/home-assistant/issues/12698 --- homeassistant/components/bmw_connected_drive.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/bmw_connected_drive.py b/homeassistant/components/bmw_connected_drive.py index 98c25df79f6..86048a56e22 100644 --- a/homeassistant/components/bmw_connected_drive.py +++ b/homeassistant/components/bmw_connected_drive.py @@ -16,7 +16,7 @@ from homeassistant.const import ( CONF_USERNAME, CONF_PASSWORD ) -REQUIREMENTS = ['bimmer_connected==0.3.0'] +REQUIREMENTS = ['bimmer_connected==0.4.1'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 88d8d19e1c8..8f8666253a8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -136,7 +136,7 @@ beautifulsoup4==4.6.0 bellows==0.5.1 # homeassistant.components.bmw_connected_drive -bimmer_connected==0.3.0 +bimmer_connected==0.4.1 # homeassistant.components.blink blinkpy==0.6.0 From 191f24b2b9c9ee4a23373ddbf48cd350eca50124 Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Wed, 28 Feb 2018 03:04:55 +0100 Subject: [PATCH 02/15] Revert optimized logbook SQL (#12762) --- homeassistant/components/logbook.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/logbook.py b/homeassistant/components/logbook.py index 1fc6d1587fc..e6e447884cb 100644 --- a/homeassistant/components/logbook.py +++ b/homeassistant/components/logbook.py @@ -47,11 +47,6 @@ CONFIG_SCHEMA = vol.Schema({ }), }, extra=vol.ALLOW_EXTRA) -ALL_EVENT_TYPES = [ - EVENT_STATE_CHANGED, EVENT_LOGBOOK_ENTRY, - EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP -] - GROUP_BY_MINUTES = 15 CONTINUOUS_DOMAINS = ['proximity', 'sensor'] @@ -271,18 +266,15 @@ def humanify(events): def _get_events(hass, config, start_day, end_day): """Get events for a period of time.""" - from homeassistant.components.recorder.models import Events, States + from homeassistant.components.recorder.models import Events from homeassistant.components.recorder.util import ( execute, session_scope) with session_scope(hass=hass) as session: - query = session.query(Events).order_by(Events.time_fired) \ - .outerjoin(States, (Events.event_id == States.event_id)) \ - .filter(Events.event_type.in_(ALL_EVENT_TYPES)) \ - .filter((Events.time_fired > start_day) - & (Events.time_fired < end_day)) \ - .filter((States.last_updated == States.last_changed) - | (States.last_updated.is_(None))) + query = session.query(Events).order_by( + Events.time_fired).filter( + (Events.time_fired > start_day) & + (Events.time_fired < end_day)) events = execute(query) return humanify(_exclude_events(events, config)) From eeb9992fde5bb276002cee0f51474b6e35ecfe4d Mon Sep 17 00:00:00 2001 From: happyleavesaoc Date: Tue, 27 Feb 2018 21:04:30 -0500 Subject: [PATCH 03/15] bump fedex version (#12764) --- homeassistant/components/sensor/fedex.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/fedex.py b/homeassistant/components/sensor/fedex.py index 0c42ef28496..f86de1d865c 100644 --- a/homeassistant/components/sensor/fedex.py +++ b/homeassistant/components/sensor/fedex.py @@ -19,7 +19,7 @@ from homeassistant.util import Throttle from homeassistant.util.dt import now, parse_date import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['fedexdeliverymanager==1.0.5'] +REQUIREMENTS = ['fedexdeliverymanager==1.0.6'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 8f8666253a8..e1fb62c626a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -268,7 +268,7 @@ evohomeclient==0.2.5 fastdotcom==0.0.3 # homeassistant.components.sensor.fedex -fedexdeliverymanager==1.0.5 +fedexdeliverymanager==1.0.6 # homeassistant.components.feedreader # homeassistant.components.sensor.geo_rss_events From 3a2c3fe58918725f98526b2170dacfb74bb7b6dc Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Wed, 28 Feb 2018 03:04:00 +0100 Subject: [PATCH 04/15] Silence harmless sonos data structure warnings (#12767) --- homeassistant/components/media_player/sonos.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/media_player/sonos.py b/homeassistant/components/media_player/sonos.py index d9236ae9a54..b86e69249b7 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -32,6 +32,7 @@ _LOGGER = logging.getLogger(__name__) # Quiet down soco logging to just actual problems. logging.getLogger('soco').setLevel(logging.WARNING) +logging.getLogger('soco.data_structures_entry').setLevel(logging.ERROR) _SOCO_SERVICES_LOGGER = logging.getLogger('soco.services') SUPPORT_SONOS = SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE |\ From a1010cc63a5ee394f99626e34a19db32f884d5d3 Mon Sep 17 00:00:00 2001 From: uchagani Date: Wed, 28 Feb 2018 01:37:12 -0500 Subject: [PATCH 05/15] Update samsungctl library to latest version (#12769) * update samsungctl library to latest version * add websocket dependency --- homeassistant/components/media_player/samsungtv.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/media_player/samsungtv.py b/homeassistant/components/media_player/samsungtv.py index 4afd578211e..0b7fc3c078e 100644 --- a/homeassistant/components/media_player/samsungtv.py +++ b/homeassistant/components/media_player/samsungtv.py @@ -23,7 +23,7 @@ from homeassistant.const import ( import homeassistant.helpers.config_validation as cv from homeassistant.util import dt as dt_util -REQUIREMENTS = ['samsungctl==0.6.0', 'wakeonlan==1.0.0'] +REQUIREMENTS = ['samsungctl[websocket]==0.7.1', 'wakeonlan==1.0.0'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index e1fb62c626a..230a13a9ca7 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1076,7 +1076,7 @@ russound_rio==0.1.4 rxv==0.5.1 # homeassistant.components.media_player.samsungtv -samsungctl==0.6.0 +samsungctl[websocket]==0.7.1 # homeassistant.components.satel_integra satel_integra==0.1.0 From 70979d855df748dab53fbbb691bca5c87759365f Mon Sep 17 00:00:00 2001 From: Bas Schipper Date: Wed, 28 Feb 2018 22:07:23 +0100 Subject: [PATCH 06/15] Fixed missing optional keyerror data_bits (#12789) --- homeassistant/components/binary_sensor/rfxtrx.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/binary_sensor/rfxtrx.py b/homeassistant/components/binary_sensor/rfxtrx.py index aedfc3364db..8c026131fd3 100644 --- a/homeassistant/components/binary_sensor/rfxtrx.py +++ b/homeassistant/components/binary_sensor/rfxtrx.py @@ -55,13 +55,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if device_id in rfxtrx.RFX_DEVICES: continue - if entity[CONF_DATA_BITS] is not None: + if entity.get(CONF_DATA_BITS) is not None: _LOGGER.debug( "Masked device id: %s", rfxtrx.get_pt2262_deviceid( - device_id, entity[CONF_DATA_BITS])) + device_id, entity.get(CONF_DATA_BITS))) _LOGGER.debug("Add %s rfxtrx.binary_sensor (class %s)", - entity[ATTR_NAME], entity[CONF_DEVICE_CLASS]) + entity[ATTR_NAME], entity.get(CONF_DEVICE_CLASS)) device = RfxtrxBinarySensor( event, entity.get(CONF_NAME), entity.get(CONF_DEVICE_CLASS), From 7511286a25c152851c6d10b1eb5038c7239cf3dd Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Wed, 28 Feb 2018 14:09:57 -0700 Subject: [PATCH 07/15] Fixed Pollen.com bugs with ZIP codes and invalid API responses (#12790) --- homeassistant/components/sensor/pollen.py | 25 ++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/sensor/pollen.py b/homeassistant/components/sensor/pollen.py index 0771e7cbd2e..98252eb6f06 100644 --- a/homeassistant/components/sensor/pollen.py +++ b/homeassistant/components/sensor/pollen.py @@ -107,7 +107,7 @@ RATING_MAPPING = [{ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_ZIP_CODE): cv.positive_int, + vol.Required(CONF_ZIP_CODE): cv.string, vol.Required(CONF_MONITORED_CONDITIONS): vol.All(cv.ensure_list, [vol.In(CONDITIONS)]), }) @@ -209,11 +209,16 @@ class AllergyAverageSensor(BaseSensor): """Update the status of the sensor.""" self.data.update() - data_attr = getattr(self.data, self._data_params['data_attr']) - indices = [ - p['Index'] - for p in data_attr['Location']['periods'] - ] + try: + data_attr = getattr(self.data, self._data_params['data_attr']) + indices = [ + p['Index'] + for p in data_attr['Location']['periods'] + ] + except KeyError: + _LOGGER.error("Pollen.com API didn't return any data") + return + average = round(mean(indices), 1) self._attrs[ATTR_TREND] = calculate_trend(indices) @@ -238,7 +243,12 @@ class AllergyIndexSensor(BaseSensor): """Update the status of the sensor.""" self.data.update() - location_data = self.data.current_data['Location'] + try: + location_data = self.data.current_data['Location'] + except KeyError: + _LOGGER.error("Pollen.com API didn't return any data") + return + [period] = [ p for p in location_data['periods'] if p['Type'] == self._data_params['key'] @@ -276,6 +286,7 @@ class DataBase(object): """Get data from a particular point in the API.""" from pypollencom.exceptions import HTTPError + data = {} try: data = getattr(getattr(self._client, module), operation)() _LOGGER.debug('Received "%s_%s" data: %s', module, From b6805853f108de57775be6bb7dfaff1295f34087 Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Thu, 1 Mar 2018 01:10:58 +0100 Subject: [PATCH 08/15] Fix dead Sonos web interface with some music sources (#12796) * Get data from soco, not event * Patch soco.events.parse_event_xml to ignore exceptions --- .../components/media_player/sonos.py | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/media_player/sonos.py b/homeassistant/components/media_player/sonos.py index b86e69249b7..b0a7776ec82 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -120,6 +120,19 @@ class SonosData: def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Sonos platform.""" import soco + import soco.events + import soco.exceptions + + orig_parse_event_xml = soco.events.parse_event_xml + + def safe_parse_event_xml(xml): + """Avoid SoCo 0.14 event thread dying from invalid xml.""" + try: + return orig_parse_event_xml(xml) + except soco.exceptions.SoCoException: + return {} + + soco.events.parse_event_xml = safe_parse_event_xml if DATA_SONOS not in hass.data: hass.data[DATA_SONOS] = SonosData() @@ -452,14 +465,14 @@ class SonosDevice(MediaPlayerDevice): def process_avtransport_event(self, event): """Process a track change event coming from a coordinator.""" - variables = event.variables + transport_info = self.soco.get_current_transport_info() + new_status = transport_info.get('current_transport_state') # Ignore transitions, we should get the target state soon - new_status = variables.get('transport_state') if new_status == 'TRANSITIONING': return - self._play_mode = variables.get('current_play_mode', self._play_mode) + self._play_mode = self.soco.play_mode if self.soco.is_playing_tv: self._refresh_linein(SOURCE_TV) @@ -473,12 +486,12 @@ class SonosDevice(MediaPlayerDevice): ) if _is_radio_uri(track_info['uri']): - self._refresh_radio(variables, media_info, track_info) + self._refresh_radio(event.variables, media_info, track_info) else: - self._refresh_music(variables, media_info, track_info) + update_position = (new_status != self._status) + self._refresh_music(update_position, media_info, track_info) - if new_status: - self._status = new_status + self._status = new_status self.schedule_update_ha_state() @@ -586,9 +599,7 @@ class SonosDevice(MediaPlayerDevice): ) else: # "On Now" field in the sonos pc app - current_track_metadata = variables.get( - 'current_track_meta_data' - ) + current_track_metadata = variables.get('current_track_meta_data') if current_track_metadata: self._media_artist = \ current_track_metadata.radio_show.split(',')[0] @@ -626,7 +637,7 @@ class SonosDevice(MediaPlayerDevice): if fav.reference.get_uri() == media_info['CurrentURI']: self._source_name = fav.title - def _refresh_music(self, variables, media_info, track_info): + def _refresh_music(self, update_media_position, media_info, track_info): """Update state when playing music tracks.""" self._extra_features = SUPPORT_PAUSE | SUPPORT_SHUFFLE_SET |\ SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK @@ -659,25 +670,21 @@ class SonosDevice(MediaPlayerDevice): rel_time = _timespan_secs(position_info.get("RelTime")) # player no longer reports position? - update_media_position = rel_time is None and \ + update_media_position |= rel_time is None and \ self._media_position is not None # player started reporting position? update_media_position |= rel_time is not None and \ self._media_position is None - if self._status != variables.get('transport_state'): - update_media_position = True - else: - # position jumped? - if rel_time is not None and self._media_position is not None: - time_diff = utcnow() - self._media_position_updated_at - time_diff = time_diff.total_seconds() + # position jumped? + if rel_time is not None and self._media_position is not None: + time_diff = utcnow() - self._media_position_updated_at + time_diff = time_diff.total_seconds() - calculated_position = self._media_position + time_diff + calculated_position = self._media_position + time_diff - update_media_position = \ - abs(calculated_position - rel_time) > 1.5 + update_media_position |= abs(calculated_position - rel_time) > 1.5 if update_media_position: self._media_position = rel_time From 59141a4063a60dade96a078aa64af308e81d2a35 Mon Sep 17 00:00:00 2001 From: Ryan McLean Date: Thu, 1 Mar 2018 01:53:51 +0000 Subject: [PATCH 09/15] Unique IDs for Plex Clients (#12799) * Unique IDs for Clients * HoundCI cleanup * debug output removal * Updates from feedback * More Updates from feedback * More Updates from feedback * Lint Fixes --- homeassistant/components/media_player/plex.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/media_player/plex.py b/homeassistant/components/media_player/plex.py index dc38bb17dd3..a63bf8525ed 100644 --- a/homeassistant/components/media_player/plex.py +++ b/homeassistant/components/media_player/plex.py @@ -6,6 +6,7 @@ https://home-assistant.io/components/media_player.plex/ """ import json import logging + from datetime import timedelta import requests @@ -47,9 +48,14 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ cv.boolean, }) +PLEX_DATA = "plex" + def setup_platform(hass, config, add_devices_callback, discovery_info=None): """Set up the Plex platform.""" + if PLEX_DATA not in hass.data: + hass.data[PLEX_DATA] = {} + # get config from plex.conf file_config = load_json(hass.config.path(PLEX_CONFIG_FILE)) @@ -130,7 +136,7 @@ def setup_plexserver( _LOGGER.info('Connected to: %s://%s', http_prefix, host) - plex_clients = {} + plex_clients = hass.data[PLEX_DATA] plex_sessions = {} track_utc_time_change(hass, lambda now: update_devices(), second=30) From 3ca446dda1a9ef89ef20505c6823b1b4aa5a4685 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 1 Mar 2018 11:52:00 -0800 Subject: [PATCH 10/15] Version bump to 0.64.2 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 82ebadd80f4..286ea2d2d78 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 = '1' +PATCH_VERSION = '2' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2) From fec7c87ff3dcb8d72d6bcd84738029e6fcb82503 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 2 Mar 2018 11:22:05 -0800 Subject: [PATCH 11/15] Version bump to 0.64.3 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 286ea2d2d78..a0e9a44ea5b 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 = '2' +PATCH_VERSION = '3' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2) From 125088449ae15aee9a36273af0b5abd826fda5be Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Thu, 1 Mar 2018 19:55:58 +0200 Subject: [PATCH 12/15] is_allowed_path: Also unit test folder #12788 #12807 (#12810) --- homeassistant/core.py | 2 +- tests/test_core.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/core.py b/homeassistant/core.py index b1cf9c51efd..6ffc524c3be 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -1068,7 +1068,7 @@ class Config(object): """Check if the path is valid for access from outside.""" assert path is not None - parent = pathlib.Path(path).parent + parent = pathlib.Path(path) try: parent = parent.resolve() # pylint: disable=no-member except (FileNotFoundError, RuntimeError, PermissionError): diff --git a/tests/test_core.py b/tests/test_core.py index 77a7872526f..261b6385b04 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -809,6 +809,7 @@ class TestConfig(unittest.TestCase): valid = [ test_file, + tmp_dir ] for path in valid: assert self.config.is_allowed_path(path) From 981f6fa02702d5f8b51a30e8258ad2a00e239447 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 2 Mar 2018 21:16:48 +0200 Subject: [PATCH 13/15] Fix sensibo default IDs to be according to schema (#12837) --- homeassistant/components/climate/sensibo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/climate/sensibo.py b/homeassistant/components/climate/sensibo.py index b49d379592f..7b4c8ed8b1b 100644 --- a/homeassistant/components/climate/sensibo.py +++ b/homeassistant/components/climate/sensibo.py @@ -29,7 +29,7 @@ REQUIREMENTS = ['pysensibo==1.0.2'] _LOGGER = logging.getLogger(__name__) -ALL = 'all' +ALL = ['all'] TIMEOUT = 10 SERVICE_ASSUME_STATE = 'sensibo_assume_state' From 4a85ab1ecb1977c01b319bb38f45cd4745e6699d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 2 Mar 2018 10:33:05 -0800 Subject: [PATCH 14/15] Cloud unauth (#12840) * Handle expired refresh token better * Retry less aggressive * Newline --- homeassistant/components/cloud/const.py | 6 ++++++ homeassistant/components/cloud/iot.py | 20 +++++++++++++++----- tests/components/cloud/test_iot.py | 18 ++++++++++++++++-- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/cloud/const.py b/homeassistant/components/cloud/const.py index b13ec6d1e45..99075d3d02d 100644 --- a/homeassistant/components/cloud/const.py +++ b/homeassistant/components/cloud/const.py @@ -16,3 +16,9 @@ MESSAGE_EXPIRATION = """ It looks like your Home Assistant Cloud subscription has expired. Please check your [account page](/config/cloud/account) to continue using the service. """ + +MESSAGE_AUTH_FAIL = """ +You have been logged out of Home Assistant Cloud because we have been unable +to verify your credentials. Please [log in](/config/cloud) again to continue +using the service. +""" diff --git a/homeassistant/components/cloud/iot.py b/homeassistant/components/cloud/iot.py index 3220fc372f7..91fbc85df6b 100644 --- a/homeassistant/components/cloud/iot.py +++ b/homeassistant/components/cloud/iot.py @@ -10,7 +10,7 @@ from homeassistant.components.google_assistant import smart_home as ga from homeassistant.util.decorator import Registry from homeassistant.helpers.aiohttp_client import async_get_clientsession from . import auth_api -from .const import MESSAGE_EXPIRATION +from .const import MESSAGE_EXPIRATION, MESSAGE_AUTH_FAIL HANDLERS = Registry() _LOGGER = logging.getLogger(__name__) @@ -77,9 +77,9 @@ class CloudIoT: self.tries += 1 try: - # Sleep 0, 5, 10, 15 ... 30 seconds between retries + # Sleep 2^tries seconds between retries self.retry_task = hass.async_add_job(asyncio.sleep( - min(30, (self.tries - 1) * 5), loop=hass.loop)) + 2**min(9, self.tries), loop=hass.loop)) yield from self.retry_task self.retry_task = None except asyncio.CancelledError: @@ -97,13 +97,23 @@ class CloudIoT: try: yield from hass.async_add_job(auth_api.check_token, self.cloud) + except auth_api.Unauthenticated as err: + _LOGGER.error('Unable to refresh token: %s', err) + + hass.components.persistent_notification.async_create( + MESSAGE_AUTH_FAIL, 'Home Assistant Cloud', + 'cloud_subscription_expired') + + # Don't await it because it will cancel this task + hass.async_add_job(self.cloud.logout()) + return except auth_api.CloudError as err: - _LOGGER.warning("Unable to connect: %s", err) + _LOGGER.warning("Unable to refresh token: %s", err) return if self.cloud.subscription_expired: hass.components.persistent_notification.async_create( - MESSAGE_EXPIRATION, 'Subscription expired', + MESSAGE_EXPIRATION, 'Home Assistant Cloud', 'cloud_subscription_expired') self.close_requested = True return diff --git a/tests/components/cloud/test_iot.py b/tests/components/cloud/test_iot.py index 3eec350b2cb..d6a26ee37e0 100644 --- a/tests/components/cloud/test_iot.py +++ b/tests/components/cloud/test_iot.py @@ -6,7 +6,7 @@ from aiohttp import WSMsgType, client_exceptions import pytest from homeassistant.setup import async_setup_component -from homeassistant.components.cloud import iot, auth_api +from homeassistant.components.cloud import Cloud, iot, auth_api, MODE_DEV from tests.components.alexa import test_smart_home as test_alexa from tests.common import mock_coro @@ -202,7 +202,7 @@ def test_cloud_check_token_raising(mock_client, caplog, mock_cloud): yield from conn.connect() - assert 'Unable to connect: BLA' in caplog.text + assert 'Unable to refresh token: BLA' in caplog.text @asyncio.coroutine @@ -348,3 +348,17 @@ def test_handler_google_actions(hass): assert device['name']['name'] == 'Config name' assert device['name']['nicknames'] == ['Config alias'] assert device['type'] == 'action.devices.types.LIGHT' + + +async def test_refresh_token_expired(hass): + """Test handling Unauthenticated error raised if refresh token expired.""" + cloud = Cloud(hass, MODE_DEV, None, None) + + with patch('homeassistant.components.cloud.auth_api.check_token', + side_effect=auth_api.Unauthenticated) as mock_check_token, \ + patch.object(hass.components.persistent_notification, + 'async_create') as mock_create: + await cloud.iot.connect() + + assert len(mock_check_token.mock_calls) == 1 + assert len(mock_create.mock_calls) == 1 From 32b6fb60d8027d726ee631a6776ec8a1df0cf283 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 2 Mar 2018 11:21:30 -0800 Subject: [PATCH 15/15] Handle Hue errors better (#12845) * Handle Hue errors better * Lint --- homeassistant/components/hue.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/hue.py b/homeassistant/components/hue.py index 36d5a1a56a0..2d64306ca74 100644 --- a/homeassistant/components/hue.py +++ b/homeassistant/components/hue.py @@ -192,7 +192,7 @@ class HueBridge(object): self.bridge = phue.Bridge( self.host, config_file_path=self.hass.config.path(self.filename)) - except ConnectionRefusedError: # Wrong host was given + except (ConnectionRefusedError, OSError): # Wrong host was given _LOGGER.error("Error connecting to the Hue bridge at %s", self.host) return @@ -201,6 +201,9 @@ class HueBridge(object): self.host) self.request_configuration() return + except Exception: # pylint: disable=broad-except + _LOGGER.exception("Unknown error connecting with Hue bridge at %s", + self.host) # If we came here and configuring this host, mark as done if self.config_request_id: