From 7dacc4a7bb20ab22b2430c92099c89c8557c4044 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 5 Dec 2016 23:39:22 -0800 Subject: [PATCH 01/12] Fix default auth influxdb (#4771) --- homeassistant/components/influxdb.py | 44 ++++++++++++++++------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/influxdb.py b/homeassistant/components/influxdb.py index 08296ad65c7..c712cf6a27e 100644 --- a/homeassistant/components/influxdb.py +++ b/homeassistant/components/influxdb.py @@ -24,23 +24,20 @@ CONF_TAGS = 'tags' CONF_DEFAULT_MEASUREMENT = 'default_measurement' DEFAULT_DATABASE = 'home_assistant' -DEFAULT_HOST = 'localhost' -DEFAULT_PORT = 8086 -DEFAULT_SSL = False -DEFAULT_VERIFY_SSL = False +DEFAULT_VERIFY_SSL = True DOMAIN = 'influxdb' TIMEOUT = 5 CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ - vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_HOST): cv.string, vol.Inclusive(CONF_USERNAME, 'authentication'): cv.string, vol.Inclusive(CONF_PASSWORD, 'authentication'): cv.string, vol.Optional(CONF_BLACKLIST, default=[]): vol.All(cv.ensure_list, [cv.entity_id]), vol.Optional(CONF_DB_NAME, default=DEFAULT_DATABASE): cv.string, - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, - vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean, + vol.Optional(CONF_PORT): cv.port, + vol.Optional(CONF_SSL): cv.boolean, vol.Optional(CONF_DEFAULT_MEASUREMENT): cv.string, vol.Optional(CONF_TAGS, default={}): vol.Schema({cv.string: cv.string}), @@ -57,23 +54,34 @@ def setup(hass, config): conf = config[DOMAIN] - host = conf.get(CONF_HOST) - port = conf.get(CONF_PORT) - database = conf.get(CONF_DB_NAME) - username = conf.get(CONF_USERNAME) - password = conf.get(CONF_PASSWORD) - ssl = conf.get(CONF_SSL) - verify_ssl = conf.get(CONF_VERIFY_SSL) + kwargs = { + 'database': conf[CONF_DB_NAME], + 'verify_ssl': conf[CONF_VERIFY_SSL], + 'timeout': TIMEOUT + } + + if CONF_HOST in conf: + kwargs['host'] = conf[CONF_HOST] + + if CONF_PORT in conf: + kwargs['port'] = conf[CONF_PORT] + + if CONF_USERNAME in conf: + kwargs['username'] = conf[CONF_USERNAME] + + if CONF_PASSWORD in conf: + kwargs['password'] = conf[CONF_PASSWORD] + + if CONF_SSL in conf: + kwargs['ssl'] = conf[CONF_SSL] + blacklist = conf.get(CONF_BLACKLIST) whitelist = conf.get(CONF_WHITELIST) tags = conf.get(CONF_TAGS) default_measurement = conf.get(CONF_DEFAULT_MEASUREMENT) try: - influx = InfluxDBClient( - host=host, port=port, username=username, password=password, - database=database, ssl=ssl, verify_ssl=verify_ssl, - timeout=TIMEOUT) + influx = InfluxDBClient(**kwargs) influx.query("select * from /.*/ LIMIT 1;") except exceptions.InfluxDBClientError as exc: _LOGGER.error("Database host is not accessible due to '%s', please " From 5e2911f0717585e25d1c2537279285d642536005 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 6 Dec 2016 07:43:11 -0800 Subject: [PATCH 02/12] Fix Kodi auth (#4770) --- homeassistant/components/media_player/kodi.py | 25 ++++++++++++++----- homeassistant/components/notify/kodi.py | 22 +++++++++++----- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/media_player/kodi.py b/homeassistant/components/media_player/kodi.py index ae9f8c8d721..68161deea2f 100644 --- a/homeassistant/components/media_player/kodi.py +++ b/homeassistant/components/media_player/kodi.py @@ -36,10 +36,10 @@ SUPPORT_KODI = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_PASSWORD): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_TURN_OFF_ACTION, default=None): vol.In(TURN_OFF_ACTION), - vol.Optional(CONF_USERNAME): cv.string, + vol.Inclusive(CONF_USERNAME, 'auth'): cv.string, + vol.Inclusive(CONF_PASSWORD, 'auth'): cv.string, }) @@ -51,11 +51,19 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if jsonrpc_url: url = jsonrpc_url.rstrip('/jsonrpc') + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + + if username is not None: + auth = (username, password) + else: + auth = None + add_devices([ KodiDevice( config.get(CONF_NAME), url, - auth=(config.get(CONF_USERNAME), config.get(CONF_PASSWORD)), + auth=auth, turn_off_action=config.get(CONF_TURN_OFF_ACTION)), ]) @@ -68,10 +76,15 @@ class KodiDevice(MediaPlayerDevice): import jsonrpc_requests self._name = name self._url = url + + kwargs = {'timeout': 5} + + if auth is not None: + kwargs['auth'] = auth + self._server = jsonrpc_requests.Server( - '{}/jsonrpc'.format(self._url), - auth=auth, - timeout=5) + '{}/jsonrpc'.format(self._url), **kwargs) + self._turn_off_action = turn_off_action self._players = list() self._properties = None diff --git a/homeassistant/components/notify/kodi.py b/homeassistant/components/notify/kodi.py index 6f725d63d47..1d95920d00b 100644 --- a/homeassistant/components/notify/kodi.py +++ b/homeassistant/components/notify/kodi.py @@ -22,8 +22,8 @@ DEFAULT_PORT = 8080 PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, - vol.Optional(CONF_USERNAME): cv.string, - vol.Optional(CONF_PASSWORD): cv.string, + vol.Inclusive(CONF_USERNAME, 'auth'): cv.string, + vol.Inclusive(CONF_PASSWORD, 'auth'): cv.string, }) ATTR_DISPLAYTIME = 'displaytime' @@ -33,7 +33,13 @@ def get_service(hass, config): """Return the notify service.""" url = '{}:{}'.format(config.get(CONF_HOST), config.get(CONF_PORT)) - auth = (config.get(CONF_USERNAME), config.get(CONF_PASSWORD)) + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + + if username is not None: + auth = (username, password) + else: + auth = None return KODINotificationService( url, @@ -48,10 +54,14 @@ class KODINotificationService(BaseNotificationService): """Initialize the service.""" import jsonrpc_requests self._url = url + + kwargs = {'timeout': 5} + + if auth is not None: + kwargs['auth'] = auth + self._server = jsonrpc_requests.Server( - '{}/jsonrpc'.format(self._url), - auth=auth, - timeout=5) + '{}/jsonrpc'.format(self._url), **kwargs) def send_message(self, message="", **kwargs): """Send a message to Kodi.""" From 0e74cd833d75c2aa1349dad36fb6922950bdadc1 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Tue, 6 Dec 2016 23:31:07 -0500 Subject: [PATCH 03/12] Updated python-nest dependency (#4785) * Updated python-nest dependency This sha fixes two issues: - min and max temperatures not being set when temperature isn't locked - fixes error when setting farenheit with a .5 * gen requirements all * Add fix for https://github.com/home-assistant/home-assistant/issues/4731 --- homeassistant/components/climate/nest.py | 14 ++++++-------- homeassistant/components/nest.py | 2 +- requirements_all.txt | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/climate/nest.py b/homeassistant/components/climate/nest.py index dbc68162579..ab41c10e6d1 100644 --- a/homeassistant/components/climate/nest.py +++ b/homeassistant/components/climate/nest.py @@ -86,6 +86,8 @@ class NestThermostat(ClimateDevice): self._eco_temperature = None self._is_locked = None self._locked_temperature = None + self._min_temperature = None + self._max_temperature = None @property def name(self): @@ -204,18 +206,12 @@ class NestThermostat(ClimateDevice): @property def min_temp(self): """Identify min_temp in Nest API or defaults if not available.""" - if self._is_locked: - return self._locked_temperature[0] - else: - return None + return self._min_temperature @property def max_temp(self): """Identify max_temp in Nest API or defaults if not available.""" - if self._is_locked: - return self._locked_temperature[1] - else: - return None + return self._max_temperature def update(self): """Cache value from Python-nest.""" @@ -229,6 +225,8 @@ class NestThermostat(ClimateDevice): self._away = self.structure.away == 'away' self._eco_temperature = self.device.eco_temperature self._locked_temperature = self.device.locked_temperature + self._min_temperature = self.device.min_temperature + self._max_temperature = self.device.max_temperature self._is_locked = self.device.is_locked if self.device.temperature_scale == 'C': self._temperature_scale = TEMP_CELSIUS diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index e19011c47b8..0952129c439 100644 --- a/homeassistant/components/nest.py +++ b/homeassistant/components/nest.py @@ -19,7 +19,7 @@ _LOGGER = logging.getLogger(__name__) REQUIREMENTS = [ 'http://github.com/technicalpickles/python-nest' - '/archive/2512973b4b390d3965da43529cd20402ad374bfa.zip' # nest-cam branch + '/archive/dd628f90772d170b9602f262d5d2e7d61bdd3cf5.zip' # nest-cam branch '#python-nest==3.0.0'] DOMAIN = 'nest' diff --git a/requirements_all.txt b/requirements_all.txt index 6ac20e51844..387fa216a82 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -164,7 +164,7 @@ hikvision==0.4 # http://github.com/adafruit/Adafruit_Python_DHT/archive/310c59b0293354d07d94375f1365f7b9b9110c7d.zip#Adafruit_DHT==1.3.0 # homeassistant.components.nest -http://github.com/technicalpickles/python-nest/archive/2512973b4b390d3965da43529cd20402ad374bfa.zip#python-nest==3.0.0 +http://github.com/technicalpickles/python-nest/archive/dd628f90772d170b9602f262d5d2e7d61bdd3cf5.zip#python-nest==3.0.0 # homeassistant.components.light.flux_led https://github.com/Danielhiversen/flux_led/archive/0.9.zip#flux_led==0.9 From 8a4aace789819622866797c6fb5fce94b1429f42 Mon Sep 17 00:00:00 2001 From: Adam Mills Date: Wed, 7 Dec 2016 00:03:49 -0500 Subject: [PATCH 04/12] Fix incorrect caching of /api/error_log (#4789) --- homeassistant/components/http/__init__.py | 4 ++-- homeassistant/components/http/static.py | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py index 11a9e755bb4..de864a0c193 100644 --- a/homeassistant/components/http/__init__.py +++ b/homeassistant/components/http/__init__.py @@ -32,7 +32,7 @@ from .const import ( KEY_USE_X_FORWARDED_FOR, KEY_TRUSTED_NETWORKS, KEY_BANS_ENABLED, KEY_LOGIN_THRESHOLD, KEY_DEVELOPMENT, KEY_AUTHENTICATED) -from .static import GZIP_FILE_SENDER, staticresource_middleware +from .static import FILE_SENDER, GZIP_FILE_SENDER, staticresource_middleware from .util import get_real_ip DOMAIN = 'http' @@ -344,7 +344,7 @@ class HomeAssistantView(object): def file(self, request, fil): """Return a file.""" assert isinstance(fil, str), 'only string paths allowed' - response = yield from GZIP_FILE_SENDER.send(request, Path(fil)) + response = yield from FILE_SENDER.send(request, Path(fil)) return response def register(self, router): diff --git a/homeassistant/components/http/static.py b/homeassistant/components/http/static.py index c8c55870e0f..0bd68d6136e 100644 --- a/homeassistant/components/http/static.py +++ b/homeassistant/components/http/static.py @@ -63,6 +63,7 @@ class GzipFileSender(FileSender): GZIP_FILE_SENDER = GzipFileSender() +FILE_SENDER = FileSender() @asyncio.coroutine From 7c3ae884dfef91d7a6346880bb950527e616a7ce Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 4 Dec 2016 07:08:24 +0100 Subject: [PATCH 05/12] Migrate remote to async (#4678) * Migrate remote to async * add coro * remove sync from init since only used in harmony * import ATTR from remote * remove unused sync stuff from tests --- homeassistant/components/remote/__init__.py | 76 +++++++++++---------- homeassistant/components/remote/harmony.py | 7 +- tests/components/remote/test_demo.py | 17 ----- tests/components/remote/test_init.py | 1 - 4 files changed, 43 insertions(+), 58 deletions(-) diff --git a/homeassistant/components/remote/__init__.py b/homeassistant/components/remote/__init__.py index 8223c33d944..d6f534eae5b 100755 --- a/homeassistant/components/remote/__init__.py +++ b/homeassistant/components/remote/__init__.py @@ -4,7 +4,9 @@ Component to interface with universal remote control devices. For more details about this component, please refer to the documentation at https://home-assistant.io/components/remote/ """ +import asyncio from datetime import timedelta +import functools as ft import logging import os @@ -80,50 +82,57 @@ def send_command(hass, device, command, entity_id=None): hass.services.call(DOMAIN, SERVICE_SEND_COMMAND, data) -def sync(hass, entity_id=None): - """Sync remote device.""" - data = {ATTR_ENTITY_ID: entity_id} if entity_id else None - hass.services.call(DOMAIN, SERVICE_SYNC, data) - - -def setup(hass, config): +@asyncio.coroutine +def async_setup(hass, config): """Track states and offer events for remotes.""" component = EntityComponent( _LOGGER, DOMAIN, hass, SCAN_INTERVAL, GROUP_NAME_ALL_REMOTES) - component.setup(config) + yield from component.async_setup(config) - def handle_remote_service(service): + @asyncio.coroutine + def async_handle_remote_service(service): """Handle calls to the remote services.""" - target_remotes = component.extract_from_service(service) + target_remotes = component.async_extract_from_service(service) activity_id = service.data.get(ATTR_ACTIVITY) device = service.data.get(ATTR_DEVICE) command = service.data.get(ATTR_COMMAND) + update_tasks = [] for remote in target_remotes: if service.service == SERVICE_TURN_ON: - remote.turn_on(activity=activity_id) + yield from remote.async_turn_on(activity=activity_id) elif service.service == SERVICE_SEND_COMMAND: - remote.send_command(device=device, command=command) - elif service.service == SERVICE_SYNC: - remote.sync() + yield from remote.async_send_command( + device=device, command=command) else: - remote.turn_off() + yield from remote.async_turn_off() if remote.should_poll: - remote.update_ha_state(True) + update_coro = remote.async_update_ha_state(True) + if hasattr(remote, 'async_update'): + update_tasks.append(hass.loop.create_task(update_coro)) + else: + yield from update_coro - descriptions = load_yaml_config_file( - os.path.join(os.path.dirname(__file__), 'services.yaml')) - hass.services.register(DOMAIN, SERVICE_TURN_OFF, handle_remote_service, - descriptions.get(SERVICE_TURN_OFF), - schema=REMOTE_SERVICE_SCHEMA) - hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_remote_service, - descriptions.get(SERVICE_TURN_ON), - schema=REMOTE_SERVICE_TURN_ON_SCHEMA) - hass.services.register(DOMAIN, SERVICE_SEND_COMMAND, handle_remote_service, - descriptions.get(SERVICE_SEND_COMMAND), - schema=REMOTE_SERVICE_SEND_COMMAND_SCHEMA) + if update_tasks: + yield from asyncio.wait(update_tasks, loop=hass.loop) + + descriptions = yield from hass.loop.run_in_executor( + None, load_yaml_config_file, os.path.join( + os.path.dirname(__file__), 'services.yaml')) + hass.services.async_register( + DOMAIN, SERVICE_TURN_OFF, async_handle_remote_service, + descriptions.get(SERVICE_TURN_OFF), + schema=REMOTE_SERVICE_SCHEMA) + hass.services.async_register( + DOMAIN, SERVICE_TURN_ON, async_handle_remote_service, + descriptions.get(SERVICE_TURN_ON), + schema=REMOTE_SERVICE_TURN_ON_SCHEMA) + hass.services.async_register( + DOMAIN, SERVICE_SEND_COMMAND, async_handle_remote_service, + descriptions.get(SERVICE_SEND_COMMAND), + schema=REMOTE_SERVICE_SEND_COMMAND_SCHEMA) return True @@ -131,14 +140,11 @@ def setup(hass, config): class RemoteDevice(ToggleEntity): """Representation of a remote.""" - def turn_on(self, **kwargs): - """Turn a device on with the remote.""" - raise NotImplementedError() - - def turn_off(self, **kwargs): - """Turn a device off with the remote.""" - raise NotImplementedError() - def send_command(self, **kwargs): """Send a command to a device.""" raise NotImplementedError() + + def async_send_command(self, **kwargs): + """Send a command to a device.""" + yield from self.hass.loop.run_in_executor( + None, ft.partial(self.send_command, **kwargs)) diff --git a/homeassistant/components/remote/harmony.py b/homeassistant/components/remote/harmony.py index 1bd1e1b94cc..60d0b29c51d 100755 --- a/homeassistant/components/remote/harmony.py +++ b/homeassistant/components/remote/harmony.py @@ -14,7 +14,8 @@ import homeassistant.components.remote as remote import homeassistant.helpers.config_validation as cv from homeassistant.const import ( CONF_NAME, CONF_HOST, CONF_PORT, ATTR_ENTITY_ID) -from homeassistant.components.remote import PLATFORM_SCHEMA, DOMAIN +from homeassistant.components.remote import ( + PLATFORM_SCHEMA, DOMAIN, ATTR_DEVICE, ATTR_COMMAND, ATTR_ACTIVITY) from homeassistant.util import slugify from homeassistant.config import load_yaml_config_file @@ -22,10 +23,6 @@ REQUIREMENTS = ['pyharmony==1.0.12'] _LOGGER = logging.getLogger(__name__) -ATTR_DEVICE = 'device' -ATTR_COMMAND = 'command' -ATTR_ACTIVITY = 'activity' - DEFAULT_PORT = 5222 DEVICES = [] diff --git a/tests/components/remote/test_demo.py b/tests/components/remote/test_demo.py index f43f9e8610c..7dc8f2c8976 100755 --- a/tests/components/remote/test_demo.py +++ b/tests/components/remote/test_demo.py @@ -9,7 +9,6 @@ from homeassistant.const import ( SERVICE_TURN_ON, SERVICE_TURN_OFF) from tests.common import get_test_home_assistant, mock_service -SERVICE_SYNC = 'sync' SERVICE_SEND_COMMAND = 'send_command' @@ -83,22 +82,6 @@ class TestDemoRemote(unittest.TestCase): self.assertEqual(SERVICE_TURN_OFF, call.service) self.assertEqual('entity_id_val', call.data[ATTR_ENTITY_ID]) - # Test sync - sync_calls = mock_service( - self.hass, remote.DOMAIN, SERVICE_SYNC) - - remote.sync( - self.hass, entity_id='entity_id_val') - - self.hass.block_till_done() - - self.assertEqual(1, len(sync_calls)) - call = sync_calls[-1] - - self.assertEqual(remote.DOMAIN, call.domain) - self.assertEqual(SERVICE_SYNC, call.service) - self.assertEqual('entity_id_val', call.data[ATTR_ENTITY_ID]) - # Test send_command send_command_calls = mock_service( self.hass, remote.DOMAIN, SERVICE_SEND_COMMAND) diff --git a/tests/components/remote/test_init.py b/tests/components/remote/test_init.py index 799ed3b5ea7..a5d711f8680 100755 --- a/tests/components/remote/test_init.py +++ b/tests/components/remote/test_init.py @@ -11,7 +11,6 @@ import homeassistant.components.remote as remote from tests.common import mock_service, get_test_home_assistant TEST_PLATFORM = {remote.DOMAIN: {CONF_PLATFORM: 'test'}} -SERVICE_SYNC = 'sync' SERVICE_SEND_COMMAND = 'send_command' From 9bca3f31037d6ea292395a17b47208c63b800088 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 6 Dec 2016 22:30:47 -0800 Subject: [PATCH 06/12] Update after service calls (#4795) * Update after service calls * Service update: wrap async_update in create_task --- .../alarm_control_panel/__init__.py | 8 ++++++-- homeassistant/components/cover/__init__.py | 17 ++++++++++++----- homeassistant/components/light/__init__.py | 19 ++++++++++++------- homeassistant/components/lock/__init__.py | 7 +++++-- homeassistant/components/remote/__init__.py | 18 +++++++++++------- homeassistant/components/switch/__init__.py | 18 +++++++++++------- 6 files changed, 57 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/__init__.py b/homeassistant/components/alarm_control_panel/__init__.py index 2030c8f88d8..49decfc62fe 100644 --- a/homeassistant/components/alarm_control_panel/__init__.py +++ b/homeassistant/components/alarm_control_panel/__init__.py @@ -59,8 +59,12 @@ def setup(hass, config): for alarm in target_alarms: getattr(alarm, method)(code) - if alarm.should_poll: - alarm.update_ha_state(True) + + for alarm in target_alarms: + if not alarm.should_poll: + continue + + alarm.update_ha_state(True) descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) diff --git a/homeassistant/components/cover/__init__.py b/homeassistant/components/cover/__init__.py index db517aec978..6c268e49be6 100644 --- a/homeassistant/components/cover/__init__.py +++ b/homeassistant/components/cover/__init__.py @@ -135,12 +135,19 @@ def setup(hass, config): params = service.data.copy() params.pop(ATTR_ENTITY_ID, None) - if method: - for cover in component.extract_from_service(service): - getattr(cover, method['method'])(**params) + if not method: + return - if cover.should_poll: - cover.update_ha_state(True) + covers = component.extract_from_service(service) + + for cover in covers: + getattr(cover, method['method'])(**params) + + for cover in covers: + if not cover.should_poll: + continue + + cover.update_ha_state(True) descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index 04eb8fabc68..869bbd90e7d 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -236,7 +236,6 @@ def async_setup(hass, config): if color_name is not None: params[ATTR_RGB_COLOR] = color_util.color_name_to_rgb(color_name) - update_tasks = [] for light in target_lights: if service.service == SERVICE_TURN_ON: yield from light.async_turn_on(**params) @@ -245,12 +244,18 @@ def async_setup(hass, config): else: yield from light.async_toggle(**params) - if light.should_poll: - update_coro = light.async_update_ha_state(True) - if hasattr(light, 'async_update'): - update_tasks.append(hass.loop.create_task(update_coro)) - else: - yield from update_coro + update_tasks = [] + + for light in target_lights: + if not light.should_poll: + continue + + update_coro = hass.loop.create_task( + light.async_update_ha_state(True)) + if hasattr(light, 'async_update'): + update_tasks.append(hass.loop.create_task(update_coro)) + else: + yield from update_coro if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) diff --git a/homeassistant/components/lock/__init__.py b/homeassistant/components/lock/__init__.py index 95db9d2b33a..e74b675733b 100644 --- a/homeassistant/components/lock/__init__.py +++ b/homeassistant/components/lock/__init__.py @@ -85,8 +85,11 @@ def setup(hass, config): else: item.unlock(code=code) - if item.should_poll: - item.update_ha_state(True) + for item in target_locks: + if not item.should_poll: + continue + + item.update_ha_state(True) descriptions = load_yaml_config_file( os.path.join(os.path.dirname(__file__), 'services.yaml')) diff --git a/homeassistant/components/remote/__init__.py b/homeassistant/components/remote/__init__.py index d6f534eae5b..3a481e83830 100755 --- a/homeassistant/components/remote/__init__.py +++ b/homeassistant/components/remote/__init__.py @@ -98,7 +98,6 @@ def async_setup(hass, config): device = service.data.get(ATTR_DEVICE) command = service.data.get(ATTR_COMMAND) - update_tasks = [] for remote in target_remotes: if service.service == SERVICE_TURN_ON: yield from remote.async_turn_on(activity=activity_id) @@ -108,12 +107,17 @@ def async_setup(hass, config): else: yield from remote.async_turn_off() - if remote.should_poll: - update_coro = remote.async_update_ha_state(True) - if hasattr(remote, 'async_update'): - update_tasks.append(hass.loop.create_task(update_coro)) - else: - yield from update_coro + update_tasks = [] + for remote in target_remotes: + if not remote.should_poll: + continue + + update_coro = hass.loop.create_task( + remote.async_update_ha_state(True)) + if hasattr(remote, 'async_update'): + update_tasks.append(hass.loop.create_task(update_coro)) + else: + yield from update_coro if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) diff --git a/homeassistant/components/switch/__init__.py b/homeassistant/components/switch/__init__.py index 02a313c675f..846a87f5067 100644 --- a/homeassistant/components/switch/__init__.py +++ b/homeassistant/components/switch/__init__.py @@ -82,7 +82,6 @@ def async_setup(hass, config): """Handle calls to the switch services.""" target_switches = component.async_extract_from_service(service) - update_tasks = [] for switch in target_switches: if service.service == SERVICE_TURN_ON: yield from switch.async_turn_on() @@ -91,12 +90,17 @@ def async_setup(hass, config): else: yield from switch.async_turn_off() - if switch.should_poll: - update_coro = switch.async_update_ha_state(True) - if hasattr(switch, 'async_update'): - update_tasks.append(hass.loop.create_task(update_coro)) - else: - yield from update_coro + update_tasks = [] + for switch in target_switches: + if not switch.should_poll: + continue + + update_coro = hass.loop.create_task( + switch.async_update_ha_state(True)) + if hasattr(switch, 'async_update'): + update_tasks.append(hass.loop.create_task(update_coro)) + else: + yield from update_coro if update_tasks: yield from asyncio.wait(update_tasks, loop=hass.loop) From e3415c4e221c7538fea24fd3ee8ac75d08e2ae50 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 6 Dec 2016 22:35:43 -0800 Subject: [PATCH 07/12] Version bump to 0.34.4 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index cc84cda9768..92107bf43a0 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 34 -PATCH_VERSION = '3' +PATCH_VERSION = '4' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2) From d17753009a61b70181aa426d3e9f350c0c9fa999 Mon Sep 17 00:00:00 2001 From: R1chardTM Date: Thu, 8 Dec 2016 06:45:43 +0100 Subject: [PATCH 08/12] Fix python-nest version bump (#4799) * Fix python-nest version bump * Change SHA so version in HASS and dependency are the same --- homeassistant/components/nest.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index 0952129c439..fd5627987a3 100644 --- a/homeassistant/components/nest.py +++ b/homeassistant/components/nest.py @@ -19,8 +19,8 @@ _LOGGER = logging.getLogger(__name__) REQUIREMENTS = [ 'http://github.com/technicalpickles/python-nest' - '/archive/dd628f90772d170b9602f262d5d2e7d61bdd3cf5.zip' # nest-cam branch - '#python-nest==3.0.0'] + '/archive/7a2eb38d391bddeb78079437f001224c370b555a.zip' # nest-cam branch + '#python-nest==3.0.1'] DOMAIN = 'nest' diff --git a/requirements_all.txt b/requirements_all.txt index 387fa216a82..a024bc15168 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -164,7 +164,7 @@ hikvision==0.4 # http://github.com/adafruit/Adafruit_Python_DHT/archive/310c59b0293354d07d94375f1365f7b9b9110c7d.zip#Adafruit_DHT==1.3.0 # homeassistant.components.nest -http://github.com/technicalpickles/python-nest/archive/dd628f90772d170b9602f262d5d2e7d61bdd3cf5.zip#python-nest==3.0.0 +http://github.com/technicalpickles/python-nest/archive/7a2eb38d391bddeb78079437f001224c370b555a.zip#python-nest==3.0.1 # homeassistant.components.light.flux_led https://github.com/Danielhiversen/flux_led/archive/0.9.zip#flux_led==0.9 From b857d5dad09ca05a1139685377cd38e409f58f65 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Fri, 9 Dec 2016 14:04:40 -0500 Subject: [PATCH 09/12] Bump python-nest to fix issue with Nest Cam without activity zones (#4820) * Bump python-nest to fix issue with Nest Cam without activity zones * bump to include fix python-nest dependency with hvac_state * regenerate requirements_all.txt --- homeassistant/components/nest.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index fd5627987a3..cd871c8e039 100644 --- a/homeassistant/components/nest.py +++ b/homeassistant/components/nest.py @@ -19,8 +19,8 @@ _LOGGER = logging.getLogger(__name__) REQUIREMENTS = [ 'http://github.com/technicalpickles/python-nest' - '/archive/7a2eb38d391bddeb78079437f001224c370b555a.zip' # nest-cam branch - '#python-nest==3.0.1'] + '/archive/b8391d2b3cb8682f8b0c2bdff477179983609f39.zip' # nest-cam branch + '#python-nest==3.0.2'] DOMAIN = 'nest' diff --git a/requirements_all.txt b/requirements_all.txt index a024bc15168..93ba123ea10 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -164,7 +164,7 @@ hikvision==0.4 # http://github.com/adafruit/Adafruit_Python_DHT/archive/310c59b0293354d07d94375f1365f7b9b9110c7d.zip#Adafruit_DHT==1.3.0 # homeassistant.components.nest -http://github.com/technicalpickles/python-nest/archive/7a2eb38d391bddeb78079437f001224c370b555a.zip#python-nest==3.0.1 +http://github.com/technicalpickles/python-nest/archive/b8391d2b3cb8682f8b0c2bdff477179983609f39.zip#python-nest==3.0.2 # homeassistant.components.light.flux_led https://github.com/Danielhiversen/flux_led/archive/0.9.zip#flux_led==0.9 From 2402897f478e809740ab5d24311c702afd570dd7 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Dec 2016 17:34:26 -0800 Subject: [PATCH 10/12] Fix Nest doing I/O inside event loop (#4855) --- homeassistant/components/sensor/nest.py | 31 +++++++++++++------------ 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/sensor/nest.py b/homeassistant/components/sensor/nest.py index 53f767ab494..b9dde96a98c 100644 --- a/homeassistant/components/sensor/nest.py +++ b/homeassistant/components/sensor/nest.py @@ -128,13 +128,20 @@ class NestSensor(Entity): # device specific self._location = self.device.where - self._name = self.device.name_long + self._name = "{} {}".format(self.device.name_long, + self.variable.replace("_", " ")) self._state = None + self._unit = None @property def name(self): """Return the name of the nest, if any.""" - return "{} {}".format(self._name, self.variable.replace("_", " ")) + return self._name + + @property + def unit_of_measurement(self): + """Return the unit the value is expressed in.""" + return self._unit class NestBasicSensor(NestSensor): @@ -145,13 +152,10 @@ class NestBasicSensor(NestSensor): """Return the state of the sensor.""" return self._state - @property - def unit_of_measurement(self): - """Return the unit the value is expressed in.""" - return SENSOR_UNITS.get(self.variable, None) - def update(self): """Retrieve latest state.""" + self._unit = SENSOR_UNITS.get(self.variable, None) + if self.variable == 'operation_mode': self._state = getattr(self.device, "mode") else: @@ -161,14 +165,6 @@ class NestBasicSensor(NestSensor): class NestTempSensor(NestSensor): """Representation of a Nest Temperature sensor.""" - @property - def unit_of_measurement(self): - """Return the unit the value is expressed in.""" - if self.device.temperature_scale == 'C': - return TEMP_CELSIUS - else: - return TEMP_FAHRENHEIT - @property def state(self): """Return the state of the sensor.""" @@ -176,6 +172,11 @@ class NestTempSensor(NestSensor): def update(self): """Retrieve latest state.""" + if self.device.temperature_scale == 'C': + self._unit = TEMP_CELSIUS + else: + self._unit = TEMP_FAHRENHEIT + temp = getattr(self.device, self.variable) if temp is None: self._state = None From 1e9d91be0ec6784be83023d6747a34d00068eda0 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Dec 2016 17:34:13 -0800 Subject: [PATCH 11/12] Fix Plex from doing I/O inside event loop (#4857) --- homeassistant/components/media_player/plex.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/media_player/plex.py b/homeassistant/components/media_player/plex.py index 76278722291..5aaee6a341e 100644 --- a/homeassistant/components/media_player/plex.py +++ b/homeassistant/components/media_player/plex.py @@ -200,6 +200,7 @@ class PlexClient(MediaPlayerDevice): self.update_devices = update_devices self.update_sessions = update_sessions self.set_device(device) + self._season = None def set_device(self, device): """Set the device property.""" @@ -240,9 +241,15 @@ class PlexClient(MediaPlayerDevice): def update(self): """Get the latest details.""" + from plexapi.video import Show + self.update_devices(no_throttle=True) self.update_sessions(no_throttle=True) + if isinstance(self.session, Show): + self._season = self._convert_na_to_none( + self.session.seasons()[0].index) + # pylint: disable=no-self-use, singleton-comparison def _convert_na_to_none(self, value): """Convert PlexAPI _NA() instances to None.""" @@ -310,9 +317,7 @@ class PlexClient(MediaPlayerDevice): @property def media_season(self): """Season of curent playing media (TV Show only).""" - from plexapi.video import Show - if isinstance(self.session, Show): - return self._convert_na_to_none(self.session.seasons()[0].index) + return self._season @property def media_series_title(self): From 96d8fbe5135da7f663a15b6f0df184b6a677a574 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Dec 2016 22:26:48 -0800 Subject: [PATCH 12/12] Version bump to 0.34.5 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 92107bf43a0..bfca70a8092 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 34 -PATCH_VERSION = '4' +PATCH_VERSION = '5' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2)