From bbb251c0cf8abf2c3e5952d7eab094fb6854f2b0 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 3 Dec 2016 12:17:16 -0800 Subject: [PATCH 001/141] Version bump to 0.35.0dev0 --- homeassistant/const.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 8e45ec4bb43..d9191eaedf2 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,8 +1,8 @@ # coding: utf-8 """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 -MINOR_VERSION = 34 -PATCH_VERSION = '0' +MINOR_VERSION = 35 +PATCH_VERSION = '0.dev0' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2) From efdf51b54296020c916ce839c2408d57f6337073 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 4 Dec 2016 00:31:27 +0100 Subject: [PATCH 002/141] Bugfix sonos hosts (#4698) --- homeassistant/components/media_player/sonos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/media_player/sonos.py b/homeassistant/components/media_player/sonos.py index b5367486e38..1fa1a39633d 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -59,7 +59,7 @@ ATTR_SLEEP_TIME = 'sleep_time' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_ADVERTISE_ADDR): cv.string, vol.Optional(CONF_INTERFACE_ADDR): cv.string, - vol.Optional(CONF_HOSTS): cv.ensure_list(cv.string), + vol.Optional(CONF_HOSTS): vol.All(cv.ensure_list, [cv.string]), }) SONOS_SCHEMA = vol.Schema({ From c89e6ec915abd6681087d3c09c1c6e1532766a64 Mon Sep 17 00:00:00 2001 From: Jacob Minnis Date: Sat, 3 Dec 2016 18:56:42 -0600 Subject: [PATCH 003/141] Updated email message headers to have 'Date' and 'Message-Id' fields (#4693) (#4695) --- homeassistant/components/notify/smtp.py | 4 ++++ tests/components/notify/test_smtp.py | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/notify/smtp.py b/homeassistant/components/notify/smtp.py index 3171509b008..6ef9bc32990 100644 --- a/homeassistant/components/notify/smtp.py +++ b/homeassistant/components/notify/smtp.py @@ -9,6 +9,7 @@ import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.image import MIMEImage +import email.utils import voluptuous as vol @@ -18,6 +19,7 @@ from homeassistant.components.notify import ( from homeassistant.const import ( CONF_USERNAME, CONF_PASSWORD, CONF_PORT, CONF_SENDER, CONF_RECIPIENT) import homeassistant.helpers.config_validation as cv +import homeassistant.util.dt as dt_util _LOGGER = logging.getLogger(__name__) @@ -134,6 +136,8 @@ class MailNotificationService(BaseNotificationService): msg['To'] = self.recipient msg['From'] = self._sender msg['X-Mailer'] = 'HomeAssistant' + msg['Date'] = email.utils.format_datetime(dt_util.now()) + msg['Message-Id'] = email.utils.make_msgid() return self._send_email(msg) diff --git a/tests/components/notify/test_smtp.py b/tests/components/notify/test_smtp.py index bbaca71ee13..6a2f8c7acbf 100644 --- a/tests/components/notify/test_smtp.py +++ b/tests/components/notify/test_smtp.py @@ -34,16 +34,18 @@ class TestNotifySmtp(unittest.TestCase): def test_text_email(self): """Test build of default text email behavior.""" msg = self.mailer.send_message('Test msg') - expected = ('Content-Type: text/plain; charset="us-ascii"\n' + expected = ('^Content-Type: text/plain; charset="us-ascii"\n' 'MIME-Version: 1.0\n' 'Content-Transfer-Encoding: 7bit\n' 'Subject: Home Assistant\n' 'To: testrecip@test.com\n' 'From: test@test.com\n' 'X-Mailer: HomeAssistant\n' + 'Date: [^\n]+\n' + 'Message-Id: <[^@]+@[^>]+>\n' '\n' - 'Test msg') - self.assertEqual(msg, expected) + 'Test msg$') + self.assertRegex(msg, expected) def test_mixed_email(self): """Test build of mixed text email behavior.""" From 97cc76b43e0156d02b723f4e0a24509f946e668a Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Sun, 4 Dec 2016 02:27:55 +0100 Subject: [PATCH 004/141] Remove global variable from tellstick code (#4700) * Refactor tellstick code for increased readability. Especially highlight if "device" is a telldus core device or a HA entity. * Refactor Tellstick object model for increased clarity. * Update comments. Unify better with sensors. Fix typo bug. Add debug logging. * Refactor tellstick code for increased readability. Especially highlight if "device" is a telldus core device or a HA entity. * Refactor Tellstick object model for increased clarity. * Update comments. Unify better with sensors. Fix typo bug. Add debug logging. * Fix lint issues. * Remove global variable according to hint from balloob. --- homeassistant/components/light/tellstick.py | 7 ++++--- homeassistant/components/switch/tellstick.py | 3 ++- homeassistant/components/tellstick.py | 13 ++++++------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/light/tellstick.py b/homeassistant/components/light/tellstick.py index 9afc826e83c..90add8f012e 100644 --- a/homeassistant/components/light/tellstick.py +++ b/homeassistant/components/light/tellstick.py @@ -29,16 +29,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None): signal_repetitions = discovery_info.get(ATTR_DISCOVER_CONFIG, DEFAULT_SIGNAL_REPETITIONS) - add_devices(TellstickLight(tellcore_id, signal_repetitions) + add_devices(TellstickLight(tellcore_id, hass.data['tellcore_registry'], + signal_repetitions) for tellcore_id in discovery_info[ATTR_DISCOVER_DEVICES]) class TellstickLight(TellstickDevice, Light): """Representation of a Tellstick light.""" - def __init__(self, tellcore_id, signal_repetitions): + def __init__(self, tellcore_id, tellcore_registry, signal_repetitions): """Initialize the light.""" - super().__init__(tellcore_id, signal_repetitions) + super().__init__(tellcore_id, tellcore_registry, signal_repetitions) self._brightness = 255 diff --git a/homeassistant/components/switch/tellstick.py b/homeassistant/components/switch/tellstick.py index d3660ab36ca..46b1ad0aa49 100644 --- a/homeassistant/components/switch/tellstick.py +++ b/homeassistant/components/switch/tellstick.py @@ -26,7 +26,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): signal_repetitions = discovery_info.get(ATTR_DISCOVER_CONFIG, DEFAULT_SIGNAL_REPETITIONS) - add_devices(TellstickSwitch(tellcore_id, signal_repetitions) + add_devices(TellstickSwitch(tellcore_id, hass.data['tellcore_registry'], + signal_repetitions) for tellcore_id in discovery_info[ATTR_DISCOVER_DEVICES]) diff --git a/homeassistant/components/tellstick.py b/homeassistant/components/tellstick.py index cbd5ff20583..e957ef5e2a8 100644 --- a/homeassistant/components/tellstick.py +++ b/homeassistant/components/tellstick.py @@ -62,8 +62,6 @@ def setup(hass, config): from tellcore.library import DirectCallbackDispatcher from tellcore.telldus import TelldusCore - global TELLCORE_REGISTRY - try: tellcore_lib = TelldusCore( callback_dispatcher=DirectCallbackDispatcher()) @@ -75,8 +73,9 @@ def setup(hass, config): all_tellcore_devices = tellcore_lib.devices() # Register devices - TELLCORE_REGISTRY = TellstickRegistry(hass, tellcore_lib) - TELLCORE_REGISTRY.register_tellcore_devices(all_tellcore_devices) + tellcore_registry = TellstickRegistry(hass, tellcore_lib) + tellcore_registry.register_tellcore_devices(all_tellcore_devices) + hass.data['tellcore_registry'] = tellcore_registry # Discover the switches _discover(hass, config, 'switch', @@ -153,17 +152,17 @@ class TellstickDevice(Entity): Contains the common logic for all Tellstick devices. """ - def __init__(self, tellcore_id, signal_repetitions): + def __init__(self, tellcore_id, tellcore_registry, signal_repetitions): """Initalize the Tellstick device.""" self._signal_repetitions = signal_repetitions self._state = None # Look up our corresponding tellcore device - self._tellcore_device = TELLCORE_REGISTRY.get_tellcore_device( + self._tellcore_device = tellcore_registry.get_tellcore_device( tellcore_id) # Query tellcore for the current state self.update() # Add ourselves to the mapping - TELLCORE_REGISTRY.register_ha_device(tellcore_id, self) + tellcore_registry.register_ha_device(tellcore_id, self) @property def should_poll(self): From cf0ff54d14ab72c2e614c98ec57de098ce736f10 Mon Sep 17 00:00:00 2001 From: Sebastian von Minckwitz Date: Sun, 4 Dec 2016 02:50:11 +0100 Subject: [PATCH 005/141] Add option to hide the group card switch (#4631) * Add option to hide the group card switch * Disallow control of hidden group switches * Revert "Disallow control of hidden group switches" This reverts commit 75e5ddfe3092327647e2873cb03ccf3b4a75b85a. * Changed hide_switch to control --- homeassistant/components/group.py | 22 ++++++++++++++++------ tests/components/test_group.py | 4 ++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/group.py b/homeassistant/components/group.py index cbdfef85942..0dfabdd8a35 100644 --- a/homeassistant/components/group.py +++ b/homeassistant/components/group.py @@ -29,11 +29,13 @@ ENTITY_ID_FORMAT = DOMAIN + '.{}' CONF_ENTITIES = 'entities' CONF_VIEW = 'view' +CONF_CONTROL = 'control' ATTR_AUTO = 'auto' ATTR_ORDER = 'order' ATTR_VIEW = 'view' ATTR_VISIBLE = 'visible' +ATTR_CONTROL = 'control' SERVICE_SET_VISIBILITY = 'set_visibility' SET_VISIBILITY_SERVICE_SCHEMA = vol.Schema({ @@ -61,6 +63,7 @@ CONFIG_SCHEMA = vol.Schema({ CONF_VIEW: cv.boolean, CONF_NAME: cv.string, CONF_ICON: cv.icon, + CONF_CONTROL: cv.string, }, cv.match_all)) }, extra=vol.ALLOW_EXTRA) @@ -206,11 +209,13 @@ def _async_process_config(hass, config, component): entity_ids = conf.get(CONF_ENTITIES) or [] icon = conf.get(CONF_ICON) view = conf.get(CONF_VIEW) + control = conf.get(CONF_CONTROL) # Don't create tasks and await them all. The order is important as # groups get a number based on creation order. group = yield from Group.async_create_group( - hass, name, entity_ids, icon=icon, view=view, object_id=object_id) + hass, name, entity_ids, icon=icon, view=view, + control=control, object_id=object_id) groups.append(group) if groups: @@ -221,7 +226,7 @@ class Group(Entity): """Track a group of entity ids.""" def __init__(self, hass, name, order=None, user_defined=True, icon=None, - view=False): + view=False, control=None): """Initialize a group. This Object has factory function for creation. @@ -239,20 +244,22 @@ class Group(Entity): self._assumed_state = False self._async_unsub_state_changed = None self._visible = True + self._control = control @staticmethod def create_group(hass, name, entity_ids=None, user_defined=True, - icon=None, view=False, object_id=None): + icon=None, view=False, control=None, object_id=None): """Initialize a group.""" return run_coroutine_threadsafe( Group.async_create_group(hass, name, entity_ids, user_defined, - icon, view, object_id), + icon, view, control, object_id), hass.loop).result() @staticmethod @asyncio.coroutine def async_create_group(hass, name, entity_ids=None, user_defined=True, - icon=None, view=False, object_id=None): + icon=None, view=False, control=None, + object_id=None): """Initialize a group. This method must be run in the event loop. @@ -260,7 +267,8 @@ class Group(Entity): group = Group( hass, name, order=len(hass.states.async_entity_ids(DOMAIN)), - user_defined=user_defined, icon=icon, view=view) + user_defined=user_defined, icon=icon, view=view, + control=control) group.entity_id = async_generate_entity_id( ENTITY_ID_FORMAT, object_id or name, hass=hass) @@ -319,6 +327,8 @@ class Group(Entity): data[ATTR_AUTO] = True if self._view: data[ATTR_VIEW] = True + if self._control: + data[ATTR_CONTROL] = self._control return data @property diff --git a/tests/components/test_group.py b/tests/components/test_group.py index c5b705cbc43..00b75c3a854 100644 --- a/tests/components/test_group.py +++ b/tests/components/test_group.py @@ -228,6 +228,7 @@ class TestComponentsGroup(unittest.TestCase): 'entities': 'light.Bowl, ' + test_group.entity_id, 'icon': 'mdi:work', 'view': True, + 'control': 'hidden', } group_conf['test_group'] = 'hello.world,sensor.happy' group_conf['empty_group'] = {'name': 'Empty Group', 'entities': None} @@ -243,6 +244,8 @@ class TestComponentsGroup(unittest.TestCase): self.assertEqual('mdi:work', group_state.attributes.get(ATTR_ICON)) self.assertTrue(group_state.attributes.get(group.ATTR_VIEW)) + self.assertEqual('hidden', + group_state.attributes.get(group.ATTR_CONTROL)) self.assertTrue(group_state.attributes.get(ATTR_HIDDEN)) self.assertEqual(1, group_state.attributes.get(group.ATTR_ORDER)) @@ -254,6 +257,7 @@ class TestComponentsGroup(unittest.TestCase): self.assertIsNone(group_state.attributes.get(group.ATTR_AUTO)) self.assertIsNone(group_state.attributes.get(ATTR_ICON)) self.assertIsNone(group_state.attributes.get(group.ATTR_VIEW)) + self.assertIsNone(group_state.attributes.get(group.ATTR_CONTROL)) self.assertIsNone(group_state.attributes.get(ATTR_HIDDEN)) self.assertEqual(2, group_state.attributes.get(group.ATTR_ORDER)) From 10d1496f5a7d72d9ad8c13d500e67b6aaa648697 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Sat, 3 Dec 2016 20:55:14 -0500 Subject: [PATCH 006/141] Updated python-nest to fix a camera bug when loading images (#4701) --- homeassistant/components/nest.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index 01f7d6ab287..e19011c47b8 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/0be5c8a6307ee81540f21aac4fcd22cc5d98c988.zip' # nest-cam branch + '/archive/2512973b4b390d3965da43529cd20402ad374bfa.zip' # nest-cam branch '#python-nest==3.0.0'] DOMAIN = 'nest' diff --git a/requirements_all.txt b/requirements_all.txt index 56772281632..aefb21a93c9 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/0be5c8a6307ee81540f21aac4fcd22cc5d98c988.zip#python-nest==3.0.0 +http://github.com/technicalpickles/python-nest/archive/2512973b4b390d3965da43529cd20402ad374bfa.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 7746ecd98ea644ecc2e6a70df209d93479c1560a Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 4 Dec 2016 02:58:44 +0100 Subject: [PATCH 007/141] Migrate weather to async (#4677) --- homeassistant/components/weather/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/weather/__init__.py b/homeassistant/components/weather/__init__.py index 26a5a41bf10..67dc7924aa3 100644 --- a/homeassistant/components/weather/__init__.py +++ b/homeassistant/components/weather/__init__.py @@ -4,6 +4,7 @@ Weather component that handles meteorological data for your location. For more details about this component, please refer to the documentation at https://home-assistant.io/components/weather/ """ +import asyncio import logging from numbers import Number @@ -30,11 +31,12 @@ ATTR_WEATHER_WIND_BEARING = 'wind_bearing' ATTR_WEATHER_WIND_SPEED = 'wind_speed' -def setup(hass, config): +@asyncio.coroutine +def async_setup(hass, config): """Setup the weather component.""" component = EntityComponent(_LOGGER, DOMAIN, hass) - component.setup(config) + yield from component.async_setup(config) return True From a099430834e702ec839fea209098449c0c71a05b Mon Sep 17 00:00:00 2001 From: Dan Date: Sat, 3 Dec 2016 23:09:28 -0500 Subject: [PATCH 008/141] Universal source list (#4086) * Add source_list to universal media player * Expanded attirubte and command support for UMP Added support to the universal media player for the following: Volume Set Current Source Set Source Current Volume The goal is to facilitate a single-card media player that includes source selection and setting the volume of the receiver. Example setup: ``` media_player: - platform: universal name: Media Center children: - media_player.kodi - media_player.cast commands: select_source: service: media_player.select_source data: entity_id: media_player.receiver volume_set: service: media_player.volume_set data: entity_id: media_player.receiver volume_mute: service: media_player.volume_mute data: entity_id: media_player.receiver turn_on: service: homeassistant.turn_on data: entity_id: media_player.receiver turn_off: service: homeassistant.turn_off data: entity_id: media_player.receiver attributes: state: media_player.receiver is_volume_muted: media_player.receiver|is_volume_muted volume_level: media_player.receiver|volume_level source: media_player.receiver|source source_list: media_player.receiver|source_list ``` * Remove print statements * Change service call back to use call_from_config * Modified service calls to use template data * linting fixes * Add tests * linting fices * More pylinting --- .../components/media_player/universal.py | 31 ++++++---- .../components/media_player/test_universal.py | 58 ++++++++++++++++++- 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/media_player/universal.py b/homeassistant/components/media_player/universal.py index 9923782872a..cedaeed4985 100644 --- a/homeassistant/components/media_player/universal.py +++ b/homeassistant/components/media_player/universal.py @@ -14,7 +14,7 @@ from homeassistant.components.media_player import ( ATTR_MEDIA_CONTENT_TYPE, ATTR_MEDIA_DURATION, ATTR_MEDIA_EPISODE, ATTR_MEDIA_PLAYLIST, ATTR_MEDIA_SEASON, ATTR_MEDIA_SEEK_POSITION, ATTR_MEDIA_SERIES_TITLE, ATTR_MEDIA_TITLE, ATTR_MEDIA_TRACK, - ATTR_MEDIA_VOLUME_LEVEL, ATTR_MEDIA_VOLUME_MUTED, + ATTR_MEDIA_VOLUME_LEVEL, ATTR_MEDIA_VOLUME_MUTED, ATTR_INPUT_SOURCE_LIST, ATTR_SUPPORTED_MEDIA_COMMANDS, DOMAIN, SERVICE_PLAY_MEDIA, SUPPORT_TURN_OFF, SUPPORT_TURN_ON, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE, SUPPORT_CLEAR_PLAYLIST, @@ -38,6 +38,7 @@ CONF_COMMANDS = 'commands' CONF_PLATFORM = 'platform' CONF_SERVICE = 'service' CONF_SERVICE_DATA = 'service_data' +ATTR_DATA = 'data' CONF_STATE = 'state' OFF_STATES = [STATE_IDLE, STATE_OFF] @@ -178,14 +179,15 @@ class UniversalMediaPlayer(MediaPlayerDevice): def _call_service(self, service_name, service_data=None, allow_override=False): """Call either a specified or active child's service.""" - if allow_override and service_name in self._cmds: - call_from_config( - self.hass, self._cmds[service_name], blocking=True) - return - if service_data is None: service_data = {} + if allow_override and service_name in self._cmds: + call_from_config( + self.hass, self._cmds[service_name], + variables=service_data, blocking=True) + return + active_child = self._child_state service_data[ATTR_ENTITY_ID] = active_child.entity_id @@ -233,7 +235,7 @@ class UniversalMediaPlayer(MediaPlayerDevice): @property def volume_level(self): """Volume level of entity specified in attributes or active child.""" - return self._child_attr(ATTR_MEDIA_VOLUME_LEVEL) + return self._override_or_child_attr(ATTR_MEDIA_VOLUME_LEVEL) @property def is_volume_muted(self): @@ -322,9 +324,14 @@ class UniversalMediaPlayer(MediaPlayerDevice): return self._child_attr(ATTR_APP_NAME) @property - def current_source(self): + def source(self): """"Return the current input source of the device.""" - return self._child_attr(ATTR_INPUT_SOURCE) + return self._override_or_child_attr(ATTR_INPUT_SOURCE) + + @property + def source_list(self): + """List of available input sources.""" + return self._override_or_child_attr(ATTR_INPUT_SOURCE_LIST) @property def supported_media_commands(self): @@ -340,6 +347,8 @@ class UniversalMediaPlayer(MediaPlayerDevice): SERVICE_VOLUME_DOWN]]): flags |= SUPPORT_VOLUME_STEP flags &= ~SUPPORT_VOLUME_SET + elif SERVICE_VOLUME_SET in self._cmds: + flags |= SUPPORT_VOLUME_SET if SERVICE_VOLUME_MUTE in self._cmds and \ ATTR_MEDIA_VOLUME_MUTED in self._attrs: @@ -376,7 +385,7 @@ class UniversalMediaPlayer(MediaPlayerDevice): def set_volume_level(self, volume_level): """Set volume level, range 0..1.""" data = {ATTR_MEDIA_VOLUME_LEVEL: volume_level} - self._call_service(SERVICE_VOLUME_SET, data) + self._call_service(SERVICE_VOLUME_SET, data, allow_override=True) def media_play(self): """Send play commmand.""" @@ -424,7 +433,7 @@ class UniversalMediaPlayer(MediaPlayerDevice): def select_source(self, source): """Set the input source.""" data = {ATTR_INPUT_SOURCE: source} - self._call_service(SERVICE_SELECT_SOURCE, data) + self._call_service(SERVICE_SELECT_SOURCE, data, allow_override=True) def clear_playlist(self): """Clear players playlist.""" diff --git a/tests/components/media_player/test_universal.py b/tests/components/media_player/test_universal.py index b7018945551..76e80f8236e 100644 --- a/tests/components/media_player/test_universal.py +++ b/tests/components/media_player/test_universal.py @@ -5,6 +5,8 @@ import unittest from homeassistant.const import ( STATE_OFF, STATE_ON, STATE_UNKNOWN, STATE_PLAYING, STATE_PAUSED) import homeassistant.components.switch as switch +import homeassistant.components.input_slider as input_slider +import homeassistant.components.input_select as input_select import homeassistant.components.media_player as media_player import homeassistant.components.media_player.universal as universal @@ -142,6 +144,17 @@ class TestMediaPlayer(unittest.TestCase): self.mock_state_switch_id = switch.ENTITY_ID_FORMAT.format('state') self.hass.states.set(self.mock_state_switch_id, STATE_OFF) + self.mock_volume_id = input_slider.ENTITY_ID_FORMAT.format( + 'volume_level') + self.hass.states.set(self.mock_volume_id, 0) + + self.mock_source_list_id = input_select.ENTITY_ID_FORMAT.format( + 'source_list') + self.hass.states.set(self.mock_source_list_id, ['dvd', 'htpc']) + + self.mock_source_id = input_select.ENTITY_ID_FORMAT.format('source') + self.hass.states.set(self.mock_source_id, 'dvd') + self.config_children_only = { 'name': 'test', 'platform': 'universal', 'children': [media_player.ENTITY_ID_FORMAT.format('mock1'), @@ -153,6 +166,9 @@ class TestMediaPlayer(unittest.TestCase): media_player.ENTITY_ID_FORMAT.format('mock2')], 'attributes': { 'is_volume_muted': self.mock_mute_switch_id, + 'volume_level': self.mock_volume_id, + 'source': self.mock_source_id, + 'source_list': self.mock_source_list_id, 'state': self.mock_state_switch_id } } @@ -405,6 +421,42 @@ class TestMediaPlayer(unittest.TestCase): ump.update() self.assertTrue(ump.is_volume_muted) + def test_source_list_children_and_attr(self): + """Test source list property w/ children and attrs.""" + config = self.config_children_and_attr + universal.validate_config(config) + + ump = universal.UniversalMediaPlayer(self.hass, **config) + + self.assertEqual("['dvd', 'htpc']", ump.source_list) + + self.hass.states.set(self.mock_source_list_id, ['dvd', 'htpc', 'game']) + self.assertEqual("['dvd', 'htpc', 'game']", ump.source_list) + + def test_source_children_and_attr(self): + """Test source property w/ children and attrs.""" + config = self.config_children_and_attr + universal.validate_config(config) + + ump = universal.UniversalMediaPlayer(self.hass, **config) + + self.assertEqual('dvd', ump.source) + + self.hass.states.set(self.mock_source_id, 'htpc') + self.assertEqual('htpc', ump.source) + + def test_volume_level_children_and_attr(self): + """Test volume level property w/ children and attrs.""" + config = self.config_children_and_attr + universal.validate_config(config) + + ump = universal.UniversalMediaPlayer(self.hass, **config) + + self.assertEqual('0', ump.volume_level) + + self.hass.states.set(self.mock_volume_id, 100) + self.assertEqual('100', ump.volume_level) + def test_is_volume_muted_children_and_attr(self): """Test is volume muted property w/ children and attrs.""" config = self.config_children_and_attr @@ -443,18 +495,20 @@ class TestMediaPlayer(unittest.TestCase): config['commands']['volume_up'] = 'test' config['commands']['volume_down'] = 'test' config['commands']['volume_mute'] = 'test' + config['commands']['volume_set'] = 'test' + config['commands']['select_source'] = 'test' ump = universal.UniversalMediaPlayer(self.hass, **config) ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name']) ump.update() - self.mock_mp_1._supported_media_commands = universal.SUPPORT_VOLUME_SET self.mock_mp_1._state = STATE_PLAYING self.mock_mp_1.update_ha_state() ump.update() check_flags = universal.SUPPORT_TURN_ON | universal.SUPPORT_TURN_OFF \ - | universal.SUPPORT_VOLUME_STEP | universal.SUPPORT_VOLUME_MUTE + | universal.SUPPORT_VOLUME_STEP | universal.SUPPORT_VOLUME_MUTE \ + | universal.SUPPORT_SELECT_SOURCE self.assertEqual(check_flags, ump.supported_media_commands) From 776e53a7f096429cc0105650c04c5563ba29ff03 Mon Sep 17 00:00:00 2001 From: Johan Bloemberg Date: Sun, 4 Dec 2016 05:45:42 +0100 Subject: [PATCH 009/141] Dsmr hourly gas usage. (#4609) * Hourly rate of Gas consumption. Use proper unknown state. * Import unknown state constant. * doh * Cleanup device add. * Fix lint. * Add test for derivative calculation. * Remove conflict. * Document and move calculation into update call. --- homeassistant/components/sensor/dsmr.py | 101 +++++++++++++++++++----- tests/components/sensor/test_dsmr.py | 36 +++++++++ 2 files changed, 117 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/sensor/dsmr.py b/homeassistant/components/sensor/dsmr.py index 8d27f7188d2..0c42033006c 100644 --- a/homeassistant/components/sensor/dsmr.py +++ b/homeassistant/components/sensor/dsmr.py @@ -26,15 +26,15 @@ stores/caches the latest telegram and notifies the Entities that the telegram has been updated. """ import asyncio -import logging from datetime import timedelta +import logging -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv from homeassistant.components.sensor import PLATFORM_SCHEMA -from homeassistant.const import CONF_PORT, EVENT_HOMEASSISTANT_STOP +from homeassistant.const import ( + CONF_PORT, EVENT_HOMEASSISTANT_STOP, STATE_UNKNOWN) +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity +import voluptuous as vol _LOGGER = logging.getLogger(__name__) @@ -65,30 +65,37 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): # Suppress logging logging.getLogger('dsmr_parser').setLevel(logging.ERROR) - from dsmr_parser import obis_references as obis + from dsmr_parser import obis_references as obis_ref from dsmr_parser.protocol import create_dsmr_reader dsmr_version = config[CONF_DSMR_VERSION] # Define list of name,obis mappings to generate entities obis_mapping = [ - ['Power Consumption', obis.CURRENT_ELECTRICITY_USAGE], - ['Power Production', obis.CURRENT_ELECTRICITY_DELIVERY], - ['Power Tariff', obis.ELECTRICITY_ACTIVE_TARIFF], - ['Power Consumption (low)', obis.ELECTRICITY_USED_TARIFF_1], - ['Power Consumption (normal)', obis.ELECTRICITY_USED_TARIFF_2], - ['Power Production (low)', obis.ELECTRICITY_DELIVERED_TARIFF_1], - ['Power Production (normal)', obis.ELECTRICITY_DELIVERED_TARIFF_2], + ['Power Consumption', obis_ref.CURRENT_ELECTRICITY_USAGE], + ['Power Production', obis_ref.CURRENT_ELECTRICITY_DELIVERY], + ['Power Tariff', obis_ref.ELECTRICITY_ACTIVE_TARIFF], + ['Power Consumption (low)', obis_ref.ELECTRICITY_USED_TARIFF_1], + ['Power Consumption (normal)', obis_ref.ELECTRICITY_USED_TARIFF_2], + ['Power Production (low)', obis_ref.ELECTRICITY_DELIVERED_TARIFF_1], + ['Power Production (normal)', obis_ref.ELECTRICITY_DELIVERED_TARIFF_2], ] - # Protocol version specific obis - if dsmr_version == '4': - obis_mapping.append(['Gas Consumption', obis.HOURLY_GAS_METER_READING]) - else: - obis_mapping.append(['Gas Consumption', obis.GAS_METER_READING]) # Generate device entities devices = [DSMREntity(name, obis) for name, obis in obis_mapping] + # Protocol version specific obis + if dsmr_version == '4': + gas_obis = obis_ref.HOURLY_GAS_METER_READING + else: + gas_obis = obis_ref.GAS_METER_READING + + # add gas meter reading and derivative for usage + devices += [ + DSMREntity('Gas Consumption', gas_obis), + DerivativeDSMREntity('Hourly Gas Consumption', gas_obis), + ] + yield from async_add_devices(devices) def update_entities_telegram(telegram): @@ -151,7 +158,10 @@ class DSMREntity(Entity): if self._obis == obis.ELECTRICITY_ACTIVE_TARIFF: return self.translate_tariff(value) else: - return value + if value: + return value + else: + return STATE_UNKNOWN @property def unit_of_measurement(self): @@ -168,4 +178,55 @@ class DSMREntity(Entity): elif value == '0001': return 'low' else: - return None + return STATE_UNKNOWN + + +class DerivativeDSMREntity(DSMREntity): + """Calculated derivative for values where the DSMR doesn't offer one. + + Gas readings are only reported per hour and don't offer a rate only + the current meter reading. This entity converts subsequents readings + into a hourly rate. + """ + + _previous_reading = None + _previous_timestamp = None + _state = STATE_UNKNOWN + + @property + def state(self): + """Return the calculated current hourly rate.""" + return self._state + + @asyncio.coroutine + def async_update(self): + """Recalculate hourly rate if timestamp has changed. + + DSMR updates gas meter reading every hour. Along with the + new value a timestamp is provided for the reading. Test + if the last known timestamp differs from the current one + then calculate a new rate for the previous hour. + """ + # check if the timestamp for the object differs from the previous one + timestamp = self.get_dsmr_object_attr('datetime') + if timestamp and timestamp != self._previous_timestamp: + current_reading = self.get_dsmr_object_attr('value') + + if self._previous_reading is None: + # can't calculate rate without previous datapoint + # just store current point + pass + else: + # recalculate the rate + diff = current_reading - self._previous_reading + self._state = diff + + self._previous_reading = current_reading + self._previous_timestamp = timestamp + + @property + def unit_of_measurement(self): + """Return the unit of measurement of this entity, per hour, if any.""" + unit = self.get_dsmr_object_attr('unit') + if unit: + return unit + '/h' diff --git a/tests/components/sensor/test_dsmr.py b/tests/components/sensor/test_dsmr.py index 166a4af9657..e76b26a811b 100644 --- a/tests/components/sensor/test_dsmr.py +++ b/tests/components/sensor/test_dsmr.py @@ -9,6 +9,8 @@ from decimal import Decimal from unittest.mock import Mock from homeassistant.bootstrap import async_setup_component +from homeassistant.components.sensor.dsmr import DerivativeDSMREntity +from homeassistant.const import STATE_UNKNOWN from tests.common import assert_setup_component @@ -62,3 +64,37 @@ def test_default_setup(hass, monkeypatch): power_tariff = hass.states.get('sensor.power_tariff') assert power_tariff.state == 'low' assert power_tariff.attributes.get('unit_of_measurement') is None + + +def test_derivative(): + """Test calculation of derivative value.""" + from dsmr_parser.objects import MBusObject + + entity = DerivativeDSMREntity('test', '1.0.0') + yield from entity.async_update() + + assert entity.state == STATE_UNKNOWN, 'initial state not unknown' + + entity.telegram = { + '1.0.0': MBusObject([ + {'value': 1}, + {'value': 1, 'unit': 'm3'}, + ]) + } + yield from entity.async_update() + + assert entity.state == STATE_UNKNOWN, \ + 'state after first update shoudl still be unknown' + + entity.telegram = { + '1.0.0': MBusObject([ + {'value': 2}, + {'value': 2, 'unit': 'm3'}, + ]) + } + yield from entity.async_update() + + assert entity.state == 1, \ + 'state should be difference between first and second update' + + assert entity.unit_of_measurement == 'm3/h' From ca63e4422701d6db8c34fe4db71677f5f63ae39b Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Sun, 4 Dec 2016 00:39:48 -0500 Subject: [PATCH 010/141] Wink hub sensor (#4704) --- .../components/binary_sensor/wink.py | 24 +++++++++++++++++++ homeassistant/components/wink.py | 2 +- requirements_all.txt | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/binary_sensor/wink.py b/homeassistant/components/binary_sensor/wink.py index 2d0e3f7226f..b129b5f24d4 100644 --- a/homeassistant/components/binary_sensor/wink.py +++ b/homeassistant/components/binary_sensor/wink.py @@ -40,6 +40,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None): for sensor in pywink.get_smoke_and_co_detectors(): add_devices([WinkBinarySensorDevice(sensor, hass)]) + for hub in pywink.get_hubs(): + add_devices([WinkHub(hub, hass)]) + class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity): """Representation of a Wink binary sensor.""" @@ -79,3 +82,24 @@ class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity): def sensor_class(self): """Return the class of this sensor, from SENSOR_CLASSES.""" return SENSOR_TYPES.get(self.capability) + + +class WinkHub(WinkDevice, BinarySensorDevice, Entity): + """Representation of a Wink Hub.""" + + def __init(self, wink, hass): + """Initialize the hub sensor.""" + WinkDevice.__init__(self, wink, hass) + + @property + def device_state_attributes(self): + """Return the state attributes.""" + return { + 'update needed': self.wink.update_needed(), + 'firmware version': self.wink.firmware_version() + } + + @property + def is_on(self): + """Return true if the binary sensor is on.""" + return self.wink.state() diff --git a/homeassistant/components/wink.py b/homeassistant/components/wink.py index bb374afaf86..affeb376f5c 100644 --- a/homeassistant/components/wink.py +++ b/homeassistant/components/wink.py @@ -15,7 +15,7 @@ from homeassistant.const import ( from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['python-wink==0.10.1', 'pubnubsub-handler==0.0.5'] +REQUIREMENTS = ['python-wink==0.11.0', 'pubnubsub-handler==0.0.5'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index aefb21a93c9..cd16e47d620 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -471,7 +471,7 @@ python-telegram-bot==5.2.0 python-twitch==1.3.0 # homeassistant.components.wink -python-wink==0.10.1 +python-wink==0.11.0 # homeassistant.components.keyboard # pyuserinput==0.1.11 From e8c9dcf0fe6f34352210f18cfcb5e7ee1e94e104 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 4 Dec 2016 07:08:24 +0100 Subject: [PATCH 011/141] 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 c25aa56751301a02e49ce64c6f70acd0c6cc4e8e Mon Sep 17 00:00:00 2001 From: Thibault Cohen Date: Sun, 4 Dec 2016 01:09:49 -0500 Subject: [PATCH 012/141] Add Sharp AquosTV component (#4679) --- .coveragerc | 1 + .../components/media_player/aquostv.py | 161 ++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 165 insertions(+) create mode 100644 homeassistant/components/media_player/aquostv.py diff --git a/.coveragerc b/.coveragerc index d0967918a60..a41a8470cb0 100644 --- a/.coveragerc +++ b/.coveragerc @@ -183,6 +183,7 @@ omit = homeassistant/components/light/x10.py homeassistant/components/light/yeelight.py homeassistant/components/lirc.py + homeassistant/components/media_player/aquostv.py homeassistant/components/media_player/braviatv.py homeassistant/components/media_player/cast.py homeassistant/components/media_player/cmus.py diff --git a/homeassistant/components/media_player/aquostv.py b/homeassistant/components/media_player/aquostv.py new file mode 100644 index 00000000000..c39986d7588 --- /dev/null +++ b/homeassistant/components/media_player/aquostv.py @@ -0,0 +1,161 @@ +""" +Support for interface with an Aquos TV. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/media_player.aquostv/ +""" +import logging + +import voluptuous as vol + +from homeassistant.components.media_player import ( + SUPPORT_TURN_ON, SUPPORT_TURN_OFF, + SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, + SUPPORT_VOLUME_SET, MediaPlayerDevice, PLATFORM_SCHEMA) + +from homeassistant.const import ( + CONF_HOST, CONF_NAME, STATE_OFF, STATE_ON, STATE_UNKNOWN, + CONF_PORT, CONF_USERNAME, CONF_PASSWORD) + + +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['sharp-aquos-rc==0.2'] + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_NAME = 'Sharp Aquos TV' +DEFAULT_PORT = 10002 +DEFAULT_USERNAME = 'admin' +DEFAULT_PASSWORD = 'password' + +SUPPORT_SHARPTV = SUPPORT_VOLUME_STEP | \ + SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \ + SUPPORT_TURN_OFF | SUPPORT_TURN_ON + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string, + vol.Optional(CONF_PASSWORD, default=DEFAULT_PASSWORD): cv.string, +}) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Sharp Aquos TV platform.""" + import sharp_aquos_rc + + name = config.get(CONF_NAME) + port = config.get(CONF_PORT) + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + + if discovery_info: + _LOGGER.debug('%s', discovery_info) + vals = discovery_info.split(':') + if len(vals) > 1: + port = vals[1] + + host = vals[0] + remote = sharp_aquos_rc.TV(host, + port, + username, + password) + add_devices([SharpAquosTVDevice(name, remote)]) + return True + + host = config.get(CONF_HOST) + remote = sharp_aquos_rc.TV(host, + port, + username, + password) + + add_devices([SharpAquosTVDevice(name, remote)]) + return True + + +# pylint: disable=abstract-method +class SharpAquosTVDevice(MediaPlayerDevice): + """Representation of a Aquos TV.""" + + # pylint: disable=too-many-public-methods + def __init__(self, name, remote): + """Initialize the aquos device.""" + # Save a reference to the imported class + self._name = name + # Assume that the TV is not muted + self._muted = False + # Assume that the TV is in Play mode + self._playing = True + self._state = STATE_UNKNOWN + self._remote = remote + self._volume = 0 + + def update(self): + """Retrieve the latest data.""" + try: + if self._remote.power() == 1: + self._state = STATE_ON + else: + self._state = STATE_OFF + + # Set TV to be able to remotely power on + # self._remote.power_on_command_settings(2) + if self._remote.mute() == 2: + self._muted = False + else: + self._muted = True + self._volume = self._remote.volume() / 60 + except OSError: + self._state = STATE_OFF + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def state(self): + """Return the state of the device.""" + return self._state + + @property + def volume_level(self): + """Volume level of the media player (0..1).""" + return self._volume + + @property + def is_volume_muted(self): + """Boolean if volume is currently muted.""" + return self._muted + + @property + def supported_media_commands(self): + """Flag of media commands that are supported.""" + return SUPPORT_SHARPTV + + def turn_off(self): + """Turn off tvplayer.""" + self._remote.power(0) + + def volume_up(self): + """Volume up the media player.""" + self._remote.volume(int(self._volume * 60) + 2) + + def volume_down(self): + """Volume down media player.""" + self._remote.volume(int(self._volume * 60) - 2) + + def set_volume_level(self, level): + """Set Volume media player.""" + self._remote.volume(int(level * 60)) + + def mute_volume(self, mute): + """Send mute command.""" + self._remote.mute(0) + + def turn_on(self): + """Turn the media player on.""" + self._remote.power(1) diff --git a/requirements_all.txt b/requirements_all.txt index cd16e47d620..65e96319843 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -509,6 +509,9 @@ scsgate==0.1.0 # homeassistant.components.notify.sendgrid sendgrid==3.6.3 +# homeassistant.components.media_player.aquostv +sharp-aquos-rc==0.2 + # homeassistant.components.notify.slack slacker==0.9.30 From 53c1b93b6139500cdd1dbe4df7c6173de1438f21 Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Sun, 4 Dec 2016 01:11:52 -0500 Subject: [PATCH 013/141] Added persistent_notification in case of error during Unifi device_tracker setup (#4682) --- homeassistant/components/device_tracker/unifi.py | 14 +++++++++++++- tests/components/device_tracker/test_unifi.py | 15 ++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/device_tracker/unifi.py b/homeassistant/components/device_tracker/unifi.py index d654c3e3eef..e139775e031 100644 --- a/homeassistant/components/device_tracker/unifi.py +++ b/homeassistant/components/device_tracker/unifi.py @@ -9,6 +9,7 @@ import urllib import voluptuous as vol import homeassistant.helpers.config_validation as cv +import homeassistant.loader as loader from homeassistant.components.device_tracker import DOMAIN, PLATFORM_SCHEMA from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD @@ -19,6 +20,9 @@ _LOGGER = logging.getLogger(__name__) CONF_PORT = 'port' CONF_SITE_ID = 'site_id' +NOTIFICATION_ID = 'unifi_notification' +NOTIFICATION_TITLE = 'Unifi Device Tracker Setup' + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_HOST, default='localhost'): cv.string, vol.Optional(CONF_SITE_ID, default='default'): cv.string, @@ -38,10 +42,18 @@ def get_scanner(hass, config): site_id = config[DOMAIN].get(CONF_SITE_ID) port = config[DOMAIN].get(CONF_PORT) + persistent_notification = loader.get_component('persistent_notification') try: ctrl = Controller(host, username, password, port, 'v4', site_id) except urllib.error.HTTPError as ex: - _LOGGER.error('Failed to connect to unifi: %s', ex) + _LOGGER.error('Failed to connect to Unifi: %s', ex) + persistent_notification.create( + hass, 'Failed to connect to Unifi. ' + 'Error: {}
' + 'You will need to restart hass after fixing.' + ''.format(ex), + title=NOTIFICATION_TITLE, + notification_id=NOTIFICATION_ID) return False return UnifiScanner(ctrl) diff --git a/tests/components/device_tracker/test_unifi.py b/tests/components/device_tracker/test_unifi.py index 32ef8976196..5482740ce11 100644 --- a/tests/components/device_tracker/test_unifi.py +++ b/tests/components/device_tracker/test_unifi.py @@ -6,6 +6,7 @@ import urllib from unifi import controller import voluptuous as vol +from tests.common import get_test_home_assistant from homeassistant.components.device_tracker import DOMAIN, unifi as unifi from homeassistant.const import (CONF_HOST, CONF_USERNAME, CONF_PASSWORD, CONF_PLATFORM) @@ -14,6 +15,14 @@ from homeassistant.const import (CONF_HOST, CONF_USERNAME, CONF_PASSWORD, class TestUnifiScanner(unittest.TestCase): """Test the Unifiy platform.""" + def setUp(self): + """Initialize values for this testcase class.""" + self.hass = get_test_home_assistant() + + def tearDown(self): + """Stop everything that was started.""" + self.hass.stop() + @mock.patch('homeassistant.components.device_tracker.unifi.UnifiScanner') @mock.patch.object(controller, 'Controller') def test_config_minimal(self, mock_ctrl, mock_scanner): @@ -25,7 +34,7 @@ class TestUnifiScanner(unittest.TestCase): CONF_PASSWORD: 'password', }) } - result = unifi.get_scanner(None, config) + result = unifi.get_scanner(self.hass, config) self.assertEqual(mock_scanner.return_value, result) self.assertEqual(mock_ctrl.call_count, 1) self.assertEqual( @@ -52,7 +61,7 @@ class TestUnifiScanner(unittest.TestCase): 'site_id': 'abcdef01', }) } - result = unifi.get_scanner(None, config) + result = unifi.get_scanner(self.hass, config) self.assertEqual(mock_scanner.return_value, result) self.assertEqual(mock_ctrl.call_count, 1) self.assertEqual( @@ -96,7 +105,7 @@ class TestUnifiScanner(unittest.TestCase): } mock_ctrl.side_effect = urllib.error.HTTPError( '/', 500, 'foo', {}, None) - result = unifi.get_scanner(None, config) + result = unifi.get_scanner(self.hass, config) self.assertFalse(result) def test_scanner_update(self): # pylint: disable=no-self-use From 4d35f2805f6c910876a6d64da579520e50d30023 Mon Sep 17 00:00:00 2001 From: DaveSergeant Date: Sat, 3 Dec 2016 23:40:22 -0800 Subject: [PATCH 014/141] New support Digital Loggers relays (#4684) * initial commit Previous work included with no history. Sorry, I was figuring out how to use git, branches and deal with open source projects. At this point this is a working switch but with the shortcomings of each of the 8 ports causes a network query. This needs to be rewritten so that the SwitchDevice is part of a larger device group that is only queried once, saving traffic and preventing the small device from timing out. * Device polls independent of switches now Used anel_pwrctrl.py as a basis to extract the per-switch polling out to per-device so it can be trottled properly. Likewise, no longer touching the device independently for relay status AND relay name. Getting them both from the same statuslist() return. * Final comments and tweaks Lowered cycle and update time since the device update is working so well now. Effectively no timeouts anymore. * Added dlipower to requirements homeassistant.components.switch.digitalloggers * Tox fixes pydocstyle updates * More tox errors * Yet more tox Removed useful future TODO and helpful details on the structure of the statuslocal list. Good catch on not initializing .update(), though it worked. * Blank line fix * Added file to .coveragerc --- .coveragerc | 1 + .../components/switch/digitalloggers.py | 148 ++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 152 insertions(+) create mode 100755 homeassistant/components/switch/digitalloggers.py diff --git a/.coveragerc b/.coveragerc index a41a8470cb0..9078b199a3e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -318,6 +318,7 @@ omit = homeassistant/components/switch/acer_projector.py homeassistant/components/switch/anel_pwrctrl.py homeassistant/components/switch/arest.py + homeassistant/components/switch/digitalloggers.py homeassistant/components/switch/dlink.py homeassistant/components/switch/edimax.py homeassistant/components/switch/hikvisioncam.py diff --git a/homeassistant/components/switch/digitalloggers.py b/homeassistant/components/switch/digitalloggers.py new file mode 100755 index 00000000000..a9d30e52ee6 --- /dev/null +++ b/homeassistant/components/switch/digitalloggers.py @@ -0,0 +1,148 @@ +""" +Support for Digital Loggers DIN III Relays. + +Support for Digital Loggers DIN III Relays and possibly other items +through Dwight Hubbard's, python-dlipower. + +For more details about python-dlipower, please see +https://github.com/dwighthubbard/python-dlipower + +Custom ports are NOT supported due to a limitation of the dlipower +library, not the digital loggers switch + +""" +import logging +from datetime import timedelta + +import voluptuous as vol + +from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) +from homeassistant.const import ( + CONF_HOST, CONF_NAME, CONF_USERNAME, CONF_PASSWORD, CONF_TIMEOUT) +import homeassistant.helpers.config_validation as cv +from homeassistant.util import Throttle + + +REQUIREMENTS = ['dlipower==0.7.165'] + +CONF_CYCLETIME = 'cycletime' + +DEFAULT_NAME = 'DINRelay' +DEFAULT_USERNAME = 'admin' +DEFAULT_PASSWORD = 'admin' +DEFAULT_TIMEOUT = 20 +DEFAULT_CYCLETIME = 2 + +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5) + +_LOGGER = logging.getLogger(__name__) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string, + vol.Optional(CONF_PASSWORD, default=DEFAULT_PASSWORD): cv.string, + vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): + vol.All(vol.Coerce(int), vol.Range(min=1, max=600)), + vol.Optional(CONF_CYCLETIME, default=DEFAULT_CYCLETIME): + vol.All(vol.Coerce(int), vol.Range(min=1, max=600)), + +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Find and return DIN III Relay switch.""" + import dlipower + + host = config.get(CONF_HOST) + controllername = config.get(CONF_NAME) + user = config.get(CONF_USERNAME) + pswd = config.get(CONF_PASSWORD) + tout = config.get(CONF_TIMEOUT) + cycl = config.get(CONF_CYCLETIME) + + power_switch = dlipower.PowerSwitch( + hostname=host, userid=user, password=pswd, + timeout=tout, cycletime=cycl + ) + + if not power_switch.verify(): + _LOGGER.error('Could not connect to DIN III Relay') + return False + + devices = [] + parent_device = DINRelayDevice(power_switch) + + devices.extend( + DINRelay(controllername, device.outlet_number, parent_device) + for device in power_switch + ) + + add_devices(devices) + + +class DINRelay(SwitchDevice): + """Representation of a individual DIN III relay port.""" + + def __init__(self, name, outletnumber, parent_device): + """Initialize the DIN III Relay switch.""" + self._parent_device = parent_device + self.controllername = name + self.outletnumber = outletnumber + self.update() + + @property + def name(self): + """Return the display name of this relay.""" + return self._outletname + + @property + def is_on(self): + """Return true if relay is on.""" + return self._is_on + + @property + def should_poll(self): + """Polling is needed.""" + return True + + def turn_on(self, **kwargs): + """Instruct the relay to turn on.""" + self._parent_device.turn_on(outlet=self.outletnumber) + + def turn_off(self, **kwargs): + """Instruct the relay to turn off.""" + self._parent_device.turn_off(outlet=self.outletnumber) + + def update(self): + """Trigger update for all switches on the parent device.""" + self._parent_device.update() + self._is_on = ( + self._parent_device.statuslocal[self.outletnumber - 1][2] == 'ON' + ) + self._outletname = "{}_{}".format( + self.controllername, + self._parent_device.statuslocal[self.outletnumber - 1][1] + ) + + +class DINRelayDevice(object): + """Device representation for per device throttling.""" + + def __init__(self, device): + """Initialize the DINRelay device.""" + self._device = device + self.update() + + def turn_on(self, **kwargs): + """Instruct the relay to turn on.""" + self._device.on(**kwargs) + + def turn_off(self, **kwargs): + """Instruct the relay to turn off.""" + self._device.off(**kwargs) + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Fetch new state data for this device.""" + self.statuslocal = self._device.statuslist() diff --git a/requirements_all.txt b/requirements_all.txt index 65e96319843..9dc2b5f0264 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -84,6 +84,9 @@ directpy==0.1 # homeassistant.components.updater distro==1.0.1 +# homeassistant.components.switch.digitalloggers +dlipower==0.7.165 + # homeassistant.components.notify.xmpp dnspython3==1.15.0 From b5c2be8ffa1dcf4e4bf2f763e7d2cbf6efe50990 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 4 Dec 2016 15:31:24 +0100 Subject: [PATCH 015/141] Protect hm thread for hangs on events (#4717) --- homeassistant/components/homematic.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index bf38b12237e..245e6a12cc2 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -544,19 +544,19 @@ def _hm_event_handler(hass, proxy, device, caller, attribute, value): # keypress event if attribute in HM_PRESS_EVENTS: - hass.bus.fire(EVENT_KEYPRESS, { + hass.add_job(hass.bus.async_fire(EVENT_KEYPRESS, { ATTR_NAME: hmdevice.NAME, ATTR_PARAM: attribute, ATTR_CHANNEL: channel - }) + })) return # impulse event if attribute in HM_IMPULSE_EVENTS: - hass.bus.fire(EVENT_KEYPRESS, { + hass.add_job(hass.bus.async_fire(EVENT_KEYPRESS, { ATTR_NAME: hmdevice.NAME, ATTR_CHANNEL: channel - }) + })) return _LOGGER.warning("Event is unknown and not forwarded to HA") From c8c6bee539273f39e4562b04f6b864845453783b Mon Sep 17 00:00:00 2001 From: hexa- Date: Sun, 4 Dec 2016 18:50:43 +0100 Subject: [PATCH 016/141] Revert "Update reference to correct tplink switch" (#4722) --- homeassistant/components/switch/tplink.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/switch/tplink.py b/homeassistant/components/switch/tplink.py index 41c1d0462b3..bcc1b329fa8 100644 --- a/homeassistant/components/switch/tplink.py +++ b/homeassistant/components/switch/tplink.py @@ -15,7 +15,7 @@ from homeassistant.const import (CONF_HOST, CONF_NAME) import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['https://github.com/GadgetReactor/pyHS100/archive/' - 'fadb76c5a0e04f4995f16055845ffedc6d658316.zip#pyHS100==0.2.1'] + '1f771b7d8090a91c6a58931532e42730b021cbde.zip#pyHS100==0.2.0'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 9dc2b5f0264..3fdf12c086a 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -173,7 +173,7 @@ http://github.com/technicalpickles/python-nest/archive/2512973b4b390d3965da43529 https://github.com/Danielhiversen/flux_led/archive/0.9.zip#flux_led==0.9 # homeassistant.components.switch.tplink -https://github.com/GadgetReactor/pyHS100/archive/fadb76c5a0e04f4995f16055845ffedc6d658316.zip#pyHS100==0.2.1 +https://github.com/GadgetReactor/pyHS100/archive/1f771b7d8090a91c6a58931532e42730b021cbde.zip#pyHS100==0.2.0 # homeassistant.components.switch.dlink https://github.com/LinuxChristian/pyW215/archive/v0.3.7.zip#pyW215==0.3.7 From 9bf13231f705c2a20d1d551cbb535ab5efacd0f8 Mon Sep 17 00:00:00 2001 From: Johan Bloemberg Date: Sun, 4 Dec 2016 18:51:40 +0100 Subject: [PATCH 017/141] Actually test calling async macvendor lookup and fix it. (#4718) --- .../components/device_tracker/__init__.py | 2 +- tests/components/device_tracker/test_init.py | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index 91f0720e927..4c27b4075e3 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -282,7 +282,7 @@ class DeviceTracker(object): list(self.group.tracking) + [device.entity_id]) # lookup mac vendor string to be stored in config - device.set_vendor_for_mac() + yield from device.set_vendor_for_mac() # update known_devices.yaml self.hass.async_add_job( diff --git a/tests/components/device_tracker/test_init.py b/tests/components/device_tracker/test_init.py index e2ee21ab90d..013920985ff 100644 --- a/tests/components/device_tracker/test_init.py +++ b/tests/components/device_tracker/test_init.py @@ -256,6 +256,24 @@ class TestComponentsDeviceTracker(unittest.TestCase): self.assertEqual(device.vendor, 'unknown') + def test_mac_vendor_lookup_on_see(self): + """Test if macvendor is looked up when device is seen.""" + mac = 'B8:27:EB:00:00:00' + vendor_string = 'Raspberry Pi Foundation' + + tracker = device_tracker.DeviceTracker( + self.hass, timedelta(seconds=60), 0, []) + + with mock_aiohttp_client() as aioclient_mock: + aioclient_mock.get('http://api.macvendors.com/b8:27:eb', + text=vendor_string) + + run_coroutine_threadsafe( + tracker.async_see(mac=mac), self.hass.loop).result() + assert aioclient_mock.call_count == 1, \ + 'No http request for macvendor made!' + self.assertEqual(tracker.devices['b827eb000000'].vendor, vendor_string) + def test_discovery(self): """Test discovery.""" scanner = get_component('device_tracker.test').SCANNER From b2a15e17d3fd846fa750b9e319779edcf0b47a99 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 4 Dec 2016 09:53:05 -0800 Subject: [PATCH 018/141] MQTT Automation: parse payload as JSON (#4703) --- homeassistant/components/automation/mqtt.py | 21 +++++++++++++++------ tests/components/automation/test_mqtt.py | 7 ++++--- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/automation/mqtt.py b/homeassistant/components/automation/mqtt.py index 39deae3d66e..4818c02d9ff 100644 --- a/homeassistant/components/automation/mqtt.py +++ b/homeassistant/components/automation/mqtt.py @@ -4,6 +4,8 @@ Offer MQTT listening automation rules. For more details about this automation rule, please refer to the documentation at https://home-assistant.io/components/automation/#mqtt-trigger """ +import json + import voluptuous as vol from homeassistant.core import callback @@ -31,13 +33,20 @@ def async_trigger(hass, config, action): def mqtt_automation_listener(msg_topic, msg_payload, qos): """Listen for MQTT messages.""" if payload is None or payload == msg_payload: + data = { + 'platform': 'mqtt', + 'topic': msg_topic, + 'payload': msg_payload, + 'qos': qos, + } + + try: + data['payload_json'] = json.loads(msg_payload) + except ValueError: + pass + hass.async_run_job(action, { - 'trigger': { - 'platform': 'mqtt', - 'topic': msg_topic, - 'payload': msg_payload, - 'qos': qos, - } + 'trigger': data }) return mqtt.async_subscribe(hass, topic, mqtt_automation_listener) diff --git a/tests/components/automation/test_mqtt.py b/tests/components/automation/test_mqtt.py index e704b9b2d64..7ee2aadeaf6 100644 --- a/tests/components/automation/test_mqtt.py +++ b/tests/components/automation/test_mqtt.py @@ -42,16 +42,17 @@ class TestAutomationMQTT(unittest.TestCase): 'service': 'test.automation', 'data_template': { 'some': '{{ trigger.platform }} - {{ trigger.topic }}' - ' - {{ trigger.payload }}' + ' - {{ trigger.payload }} - ' + '{{ trigger.payload_json.hello }}' }, } } }) - fire_mqtt_message(self.hass, 'test-topic', 'test_payload') + fire_mqtt_message(self.hass, 'test-topic', '{ "hello": "world" }') self.hass.block_till_done() self.assertEqual(1, len(self.calls)) - self.assertEqual('mqtt - test-topic - test_payload', + self.assertEqual('mqtt - test-topic - { "hello": "world" } - world', self.calls[0].data['some']) automation.turn_off(self.hass) From 93872590b67424784c3fe309978ee0bcac935ffa Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 4 Dec 2016 09:54:49 -0800 Subject: [PATCH 019/141] Fix synology dsm doing I/O inside loop (#4699) --- .../components/sensor/synologydsm.py | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/sensor/synologydsm.py b/homeassistant/components/sensor/synologydsm.py index 31201879207..6dc23a71d9b 100644 --- a/homeassistant/components/sensor/synologydsm.py +++ b/homeassistant/components/sensor/synologydsm.py @@ -151,15 +151,9 @@ class SynoApi(): except: _LOGGER.error("Error setting up Synology DSM") - def utilisation(self): - """Return utilisation information from API.""" - if self._api is not None: - return self._api.utilisation - - def storage(self): - """Return storage information from API.""" - if self._api is not None: - return self._api.storage + # Will be updated when `update` gets called. + self.utilisation = self._api.utilisation + self.storage = self._api.storage @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): @@ -219,14 +213,14 @@ class SynoNasUtilSensor(SynoNasSensor): 'memory_total_swap', 'memory_total_real'] if self.var_id in network_sensors or self.var_id in memory_sensors: - attr = getattr(self._api.utilisation(), self.var_id)(False) + attr = getattr(self._api.utilisation, self.var_id)(False) if self.var_id in network_sensors: return round(attr / 1024.0, 1) elif self.var_id in memory_sensors: return round(attr / 1024.0 / 1024.0, 1) else: - return getattr(self._api.utilisation(), self.var_id) + return getattr(self._api.utilisation, self.var_id) class SynoNasStorageSensor(SynoNasSensor): @@ -240,7 +234,7 @@ class SynoNasStorageSensor(SynoNasSensor): if self.monitor_device is not None: if self.var_id in temp_sensors: - attr = getattr(self._api.storage(), + attr = getattr(self._api.storage, self.var_id)(self.monitor_device) if self._api.temp_unit == TEMP_CELSIUS: @@ -248,5 +242,5 @@ class SynoNasStorageSensor(SynoNasSensor): else: return round(attr * 1.8 + 32.0, 1) else: - return getattr(self._api.storage(), + return getattr(self._api.storage, self.var_id)(self.monitor_device) From 1b35f0878ee75f1b87587a6f60d6786b9fa6290d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 4 Dec 2016 10:57:24 -0800 Subject: [PATCH 020/141] Fix CORS when static resources registered (#4727) --- homeassistant/components/http/__init__.py | 6 ++++++ tests/components/http/test_init.py | 7 ++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py index dc18dd2481d..11a9e755bb4 100644 --- a/homeassistant/components/http/__init__.py +++ b/homeassistant/components/http/__init__.py @@ -277,9 +277,15 @@ class HomeAssistantWSGI(object): @asyncio.coroutine def start(self): """Start the wsgi server.""" + cors_added = set() if self.cors is not None: for route in list(self.app.router.routes()): + if hasattr(route, 'resource'): + route = route.resource + if route in cors_added: + continue self.cors.add(route) + cors_added.add(route) if self.ssl_certificate: context = ssl.SSLContext(SSL_VERSION) diff --git a/tests/components/http/test_init.py b/tests/components/http/test_init.py index cd0d4fe1ffa..f50e1fb9dbf 100644 --- a/tests/components/http/test_init.py +++ b/tests/components/http/test_init.py @@ -44,6 +44,10 @@ def setUpModule(): bootstrap.setup_component(hass, 'api') + # Registering static path as it caused CORS to blow up + hass.http.register_static_path( + '/custom_components', hass.config.path('custom_components')) + hass.start() @@ -53,11 +57,12 @@ def tearDownModule(): hass.stop() -class TestHttp: +class TestCors: """Test HTTP component.""" def test_cors_allowed_with_password_in_url(self): """Test cross origin resource sharing with password in url.""" + req = requests.get(_url(const.URL_API), params={'api_password': API_PASSWORD}, headers={const.HTTP_HEADER_ORIGIN: HTTP_BASE_URL}) From a9be6c36f1129eb32377f3fc994606337ce3b929 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 4 Dec 2016 10:57:48 -0800 Subject: [PATCH 021/141] Re-org emulated_hue and fix google home (#4708) --- homeassistant/components/emulated_hue.py | 566 ------------- .../components/emulated_hue/__init__.py | 198 +++++ .../components/emulated_hue/hue_api.py | 275 ++++++ homeassistant/components/emulated_hue/upnp.py | 166 ++++ tests/components/emulated_hue/__init__.py | 1 + .../test_hue_api.py} | 784 ++++++++---------- tests/components/emulated_hue/test_init.py | 55 ++ tests/components/emulated_hue/test_upnp.py | 120 +++ 8 files changed, 1170 insertions(+), 995 deletions(-) delete mode 100644 homeassistant/components/emulated_hue.py create mode 100644 homeassistant/components/emulated_hue/__init__.py create mode 100644 homeassistant/components/emulated_hue/hue_api.py create mode 100644 homeassistant/components/emulated_hue/upnp.py create mode 100644 tests/components/emulated_hue/__init__.py rename tests/components/{test_emulated_hue.py => emulated_hue/test_hue_api.py} (78%) mode change 100755 => 100644 create mode 100755 tests/components/emulated_hue/test_init.py create mode 100644 tests/components/emulated_hue/test_upnp.py diff --git a/homeassistant/components/emulated_hue.py b/homeassistant/components/emulated_hue.py deleted file mode 100644 index 7fd187daa4d..00000000000 --- a/homeassistant/components/emulated_hue.py +++ /dev/null @@ -1,566 +0,0 @@ -""" -Support for local control of entities by emulating the Phillips Hue bridge. - -For more details about this component, please refer to the documentation at -https://home-assistant.io/components/emulated_hue/ -""" -import asyncio -import threading -import socket -import logging -import os -import select - -from aiohttp import web -import voluptuous as vol - -from homeassistant import util, core -from homeassistant.const import ( - ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON, - EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, - STATE_ON, STATE_OFF, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, -) -from homeassistant.components.light import ( - ATTR_BRIGHTNESS, ATTR_SUPPORTED_FEATURES, SUPPORT_BRIGHTNESS -) -from homeassistant.components.http import ( - HomeAssistantView, HomeAssistantWSGI -) -import homeassistant.helpers.config_validation as cv - -DOMAIN = 'emulated_hue' - -_LOGGER = logging.getLogger(__name__) - -CONF_HOST_IP = 'host_ip' -CONF_LISTEN_PORT = 'listen_port' -CONF_OFF_MAPS_TO_ON_DOMAINS = 'off_maps_to_on_domains' -CONF_EXPOSE_BY_DEFAULT = 'expose_by_default' -CONF_EXPOSED_DOMAINS = 'exposed_domains' - -ATTR_EMULATED_HUE = 'emulated_hue' -ATTR_EMULATED_HUE_NAME = 'emulated_hue_name' - -DEFAULT_LISTEN_PORT = 8300 -DEFAULT_OFF_MAPS_TO_ON_DOMAINS = ['script', 'scene'] -DEFAULT_EXPOSE_BY_DEFAULT = True -DEFAULT_EXPOSED_DOMAINS = [ - 'switch', 'light', 'group', 'input_boolean', 'media_player', 'fan' -] - -HUE_API_STATE_ON = 'on' -HUE_API_STATE_BRI = 'bri' - -CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({ - vol.Optional(CONF_HOST_IP): cv.string, - vol.Optional(CONF_LISTEN_PORT, default=DEFAULT_LISTEN_PORT): - vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), - vol.Optional(CONF_OFF_MAPS_TO_ON_DOMAINS): cv.ensure_list, - vol.Optional(CONF_EXPOSE_BY_DEFAULT): cv.boolean, - vol.Optional(CONF_EXPOSED_DOMAINS): cv.ensure_list - }) -}, extra=vol.ALLOW_EXTRA) - - -def setup(hass, yaml_config): - """Activate the emulated_hue component.""" - config = Config(yaml_config) - - server = HomeAssistantWSGI( - hass, - development=False, - server_host=config.host_ip_addr, - server_port=config.listen_port, - api_password=None, - ssl_certificate=None, - ssl_key=None, - cors_origins=None, - use_x_forwarded_for=False, - trusted_networks=[], - login_threshold=0, - is_ban_enabled=False - ) - - server.register_view(DescriptionXmlView(config)) - server.register_view(HueUsernameView) - server.register_view(HueLightsView(config)) - - upnp_listener = UPNPResponderThread( - config.host_ip_addr, config.listen_port) - - @asyncio.coroutine - def stop_emulated_hue_bridge(event): - """Stop the emulated hue bridge.""" - upnp_listener.stop() - yield from server.stop() - - @asyncio.coroutine - def start_emulated_hue_bridge(event): - """Start the emulated hue bridge.""" - upnp_listener.start() - hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, - stop_emulated_hue_bridge) - yield from server.start() - - hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_emulated_hue_bridge) - - return True - - -class Config(object): - """Holds configuration variables for the emulated hue bridge.""" - - def __init__(self, yaml_config): - """Initialize the instance.""" - conf = yaml_config.get(DOMAIN, {}) - - # Get the IP address that will be passed to the Echo during discovery - self.host_ip_addr = conf.get(CONF_HOST_IP) - if self.host_ip_addr is None: - self.host_ip_addr = util.get_local_ip() - _LOGGER.warning( - "Listen IP address not specified, auto-detected address is %s", - self.host_ip_addr) - - # Get the port that the Hue bridge will listen on - self.listen_port = conf.get(CONF_LISTEN_PORT) - if not isinstance(self.listen_port, int): - self.listen_port = DEFAULT_LISTEN_PORT - _LOGGER.warning( - "Listen port not specified, defaulting to %s", - self.listen_port) - - # Get domains that cause both "on" and "off" commands to map to "on" - # This is primarily useful for things like scenes or scripts, which - # don't really have a concept of being off - self.off_maps_to_on_domains = conf.get(CONF_OFF_MAPS_TO_ON_DOMAINS) - if not isinstance(self.off_maps_to_on_domains, list): - self.off_maps_to_on_domains = DEFAULT_OFF_MAPS_TO_ON_DOMAINS - - # Get whether or not entities should be exposed by default, or if only - # explicitly marked ones will be exposed - self.expose_by_default = conf.get( - CONF_EXPOSE_BY_DEFAULT, DEFAULT_EXPOSE_BY_DEFAULT) - - # Get domains that are exposed by default when expose_by_default is - # True - self.exposed_domains = conf.get( - CONF_EXPOSED_DOMAINS, DEFAULT_EXPOSED_DOMAINS) - - -class DescriptionXmlView(HomeAssistantView): - """Handles requests for the description.xml file.""" - - url = '/description.xml' - name = 'description:xml' - requires_auth = False - - def __init__(self, config): - """Initialize the instance of the view.""" - self.config = config - - @core.callback - def get(self, request): - """Handle a GET request.""" - xml_template = """ - - -1 -0 - -http://{0}:{1}/ - -urn:schemas-upnp-org:device:Basic:1 -HASS Bridge ({0}) -Royal Philips Electronics -http://www.philips.com -Philips hue Personal Wireless Lighting -Philips hue bridge 2015 -BSB002 -http://www.meethue.com -1234 -uuid:2f402f80-da50-11e1-9b23-001788255acc - - -""" - - resp_text = xml_template.format( - self.config.host_ip_addr, self.config.listen_port) - - return web.Response(text=resp_text, content_type='text/xml') - - -class HueUsernameView(HomeAssistantView): - """Handle requests to create a username for the emulated hue bridge.""" - - url = '/api' - name = 'hue:api' - extra_urls = ['/api/'] - requires_auth = False - - @asyncio.coroutine - def post(self, request): - """Handle a POST request.""" - try: - data = yield from request.json() - except ValueError: - return self.json_message('Invalid JSON', HTTP_BAD_REQUEST) - - if 'devicetype' not in data: - return self.json_message('devicetype not specified', - HTTP_BAD_REQUEST) - - return self.json([{'success': {'username': '12345678901234567890'}}]) - - -class HueLightsView(HomeAssistantView): - """Handle requests for getting and setting info about entities.""" - - url = '/api/{username}/lights' - name = 'api:username:lights' - extra_urls = ['/api/{username}/lights/{entity_id}', - '/api/{username}/lights/{entity_id}/state'] - requires_auth = False - - def __init__(self, config): - """Initialize the instance of the view.""" - self.config = config - self.cached_states = {} - - @core.callback - def get(self, request, username, entity_id=None): - """Handle a GET request.""" - hass = request.app['hass'] - - if entity_id is None: - return self.async_get_lights_list(hass) - - if not request.path.endswith('state'): - return self.async_get_light_state(hass, entity_id) - - return web.Response(text="Method not allowed", status=405) - - @asyncio.coroutine - def put(self, request, username, entity_id=None): - """Handle a PUT request.""" - hass = request.app['hass'] - - if not request.path.endswith('state'): - return web.Response(text="Method not allowed", status=405) - - if entity_id and hass.states.get(entity_id) is None: - return self.json_message('Entity not found', HTTP_NOT_FOUND) - - try: - json_data = yield from request.json() - except ValueError: - return self.json_message('Invalid JSON', HTTP_BAD_REQUEST) - - result = yield from self.async_put_light_state(hass, json_data, - entity_id) - return result - - @core.callback - def async_get_lights_list(self, hass): - """Process a request to get the list of available lights.""" - json_response = {} - - for entity in hass.states.async_all(): - if self.is_entity_exposed(entity): - json_response[entity.entity_id] = entity_to_json(entity) - - return self.json(json_response) - - @core.callback - def async_get_light_state(self, hass, entity_id): - """Process a request to get the state of an individual light.""" - entity = hass.states.get(entity_id) - if entity is None or not self.is_entity_exposed(entity): - return web.Response(text="Entity not found", status=404) - - cached_state = self.cached_states.get(entity_id, None) - - if cached_state is None: - final_state = entity.state == STATE_ON - final_brightness = entity.attributes.get( - ATTR_BRIGHTNESS, 255 if final_state else 0) - else: - final_state, final_brightness = cached_state - - json_response = entity_to_json(entity, final_state, final_brightness) - - return self.json(json_response) - - @asyncio.coroutine - def async_put_light_state(self, hass, request_json, entity_id): - """Process a request to set the state of an individual light.""" - config = self.config - - # Retrieve the entity from the state machine - entity = hass.states.get(entity_id) - if entity is None: - return web.Response(text="Entity not found", status=404) - - if not self.is_entity_exposed(entity): - return web.Response(text="Entity not found", status=404) - - # Parse the request into requested "on" status and brightness - parsed = parse_hue_api_put_light_body(request_json, entity) - - if parsed is None: - return web.Response(text="Bad request", status=400) - - result, brightness = parsed - - # Convert the resulting "on" status into the service we need to call - service = SERVICE_TURN_ON if result else SERVICE_TURN_OFF - - # Construct what we need to send to the service - data = {ATTR_ENTITY_ID: entity_id} - - # If the requested entity is a script add some variables - if entity.domain.lower() == "script": - data['variables'] = { - 'requested_state': STATE_ON if result else STATE_OFF - } - - if brightness is not None: - data['variables']['requested_level'] = brightness - - elif brightness is not None: - data[ATTR_BRIGHTNESS] = brightness - - if entity.domain.lower() in config.off_maps_to_on_domains: - # Map the off command to on - service = SERVICE_TURN_ON - - # Caching is required because things like scripts and scenes won't - # report as "off" to Alexa if an "off" command is received, because - # they'll map to "on". Thus, instead of reporting its actual - # status, we report what Alexa will want to see, which is the same - # as the actual requested command. - self.cached_states[entity_id] = (result, brightness) - - # Perform the requested action - yield from hass.services.async_call(core.DOMAIN, service, data, - blocking=True) - - json_response = \ - [create_hue_success_response(entity_id, HUE_API_STATE_ON, result)] - - if brightness is not None: - json_response.append(create_hue_success_response( - entity_id, HUE_API_STATE_BRI, brightness)) - - return self.json(json_response) - - def is_entity_exposed(self, entity): - """Determine if an entity should be exposed on the emulated bridge. - - Async friendly. - """ - config = self.config - - if entity.attributes.get('view') is not None: - # Ignore entities that are views - return False - - domain = entity.domain.lower() - explicit_expose = entity.attributes.get(ATTR_EMULATED_HUE, None) - - domain_exposed_by_default = \ - config.expose_by_default and domain in config.exposed_domains - - # Expose an entity if the entity's domain is exposed by default and - # the configuration doesn't explicitly exclude it from being - # exposed, or if the entity is explicitly exposed - is_default_exposed = \ - domain_exposed_by_default and explicit_expose is not False - - return is_default_exposed or explicit_expose - - -def parse_hue_api_put_light_body(request_json, entity): - """Parse the body of a request to change the state of a light.""" - if HUE_API_STATE_ON in request_json: - if not isinstance(request_json[HUE_API_STATE_ON], bool): - return None - - if request_json['on']: - # Echo requested device be turned on - brightness = None - report_brightness = False - result = True - else: - # Echo requested device be turned off - brightness = None - report_brightness = False - result = False - - if HUE_API_STATE_BRI in request_json: - # Make sure the entity actually supports brightness - entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) - - if (entity_features & SUPPORT_BRIGHTNESS) == SUPPORT_BRIGHTNESS: - try: - # Clamp brightness from 0 to 255 - brightness = \ - max(0, min(int(request_json[HUE_API_STATE_BRI]), 255)) - except ValueError: - return None - - report_brightness = True - result = (brightness > 0) - elif entity.domain.lower() == "script": - # Convert 0-255 to 0-100 - level = int(request_json[HUE_API_STATE_BRI]) / 255 * 100 - - brightness = round(level) - report_brightness = True - result = True - - return (result, brightness) if report_brightness else (result, None) - - -def entity_to_json(entity, is_on=None, brightness=None): - """Convert an entity to its Hue bridge JSON representation.""" - if is_on is None: - is_on = entity.state == STATE_ON - - if brightness is None: - brightness = 255 if is_on else 0 - - name = entity.attributes.get( - ATTR_EMULATED_HUE_NAME, entity.attributes[ATTR_FRIENDLY_NAME]) - - return { - 'state': - { - HUE_API_STATE_ON: is_on, - HUE_API_STATE_BRI: brightness, - 'reachable': True - }, - 'type': 'Dimmable light', - 'name': name, - 'modelid': 'HASS123', - 'uniqueid': entity.entity_id, - 'swversion': '123' - } - - -def create_hue_success_response(entity_id, attr, value): - """Create a success response for an attribute set on a light.""" - success_key = '/lights/{}/state/{}'.format(entity_id, attr) - return {'success': {success_key: value}} - - -class UPNPResponderThread(threading.Thread): - """Handle responding to UPNP/SSDP discovery requests.""" - - _interrupted = False - - def __init__(self, host_ip_addr, listen_port): - """Initialize the class.""" - threading.Thread.__init__(self) - - self.host_ip_addr = host_ip_addr - self.listen_port = listen_port - - # Note that the double newline at the end of - # this string is required per the SSDP spec - resp_template = """HTTP/1.1 200 OK -CACHE-CONTROL: max-age=60 -EXT: -LOCATION: http://{0}:{1}/description.xml -SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/0.1 -ST: urn:schemas-upnp-org:device:basic:1 -USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1 - -""" - - self.upnp_response = resp_template.format(host_ip_addr, listen_port) \ - .replace("\n", "\r\n") \ - .encode('utf-8') - - # Set up a pipe for signaling to the receiver that it's time to - # shutdown. Essentially, we place the SSDP socket into nonblocking - # mode and use select() to wait for data to arrive on either the SSDP - # socket or the pipe. If data arrives on either one, select() returns - # and tells us which filenos have data ready to read. - # - # When we want to stop the responder, we write data to the pipe, which - # causes the select() to return and indicate that said pipe has data - # ready to be read, which indicates to us that the responder needs to - # be shutdown. - self._interrupted_read_pipe, self._interrupted_write_pipe = os.pipe() - - def run(self): - """Run the server.""" - # Listen for UDP port 1900 packets sent to SSDP multicast address - ssdp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - ssdp_socket.setblocking(False) - - # Required for receiving multicast - ssdp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - ssdp_socket.setsockopt( - socket.SOL_IP, - socket.IP_MULTICAST_IF, - socket.inet_aton(self.host_ip_addr)) - - ssdp_socket.setsockopt( - socket.SOL_IP, - socket.IP_ADD_MEMBERSHIP, - socket.inet_aton("239.255.255.250") + - socket.inet_aton(self.host_ip_addr)) - - ssdp_socket.bind(("239.255.255.250", 1900)) - - while True: - if self._interrupted: - clean_socket_close(ssdp_socket) - return - - try: - read, _, _ = select.select( - [self._interrupted_read_pipe, ssdp_socket], [], - [ssdp_socket]) - - if self._interrupted_read_pipe in read: - # Implies self._interrupted is True - clean_socket_close(ssdp_socket) - return - elif ssdp_socket in read: - data, addr = ssdp_socket.recvfrom(1024) - else: - continue - except socket.error as ex: - if self._interrupted: - clean_socket_close(ssdp_socket) - return - - _LOGGER.error("UPNP Responder socket exception occured: %s", - ex.__str__) - - if "M-SEARCH" in data.decode('utf-8'): - # SSDP M-SEARCH method received, respond to it with our info - resp_socket = socket.socket( - socket.AF_INET, socket.SOCK_DGRAM) - - resp_socket.sendto(self.upnp_response, addr) - resp_socket.close() - - def stop(self): - """Stop the server.""" - # Request for server - self._interrupted = True - os.write(self._interrupted_write_pipe, bytes([0])) - self.join() - - -def clean_socket_close(sock): - """Close a socket connection and logs its closure.""" - _LOGGER.info("UPNP responder shutting down.") - - sock.close() diff --git a/homeassistant/components/emulated_hue/__init__.py b/homeassistant/components/emulated_hue/__init__.py new file mode 100644 index 00000000000..2efce06528d --- /dev/null +++ b/homeassistant/components/emulated_hue/__init__.py @@ -0,0 +1,198 @@ +""" +Support for local control of entities by emulating the Phillips Hue bridge. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/emulated_hue/ +""" +import asyncio +import logging + +import voluptuous as vol + +from homeassistant import util +from homeassistant.const import ( + EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, +) +from homeassistant.components.http import HomeAssistantWSGI +import homeassistant.helpers.config_validation as cv +from .hue_api import ( + HueUsernameView, HueAllLightsStateView, HueOneLightStateView, + HueOneLightChangeView) +from .upnp import DescriptionXmlView, UPNPResponderThread + +DOMAIN = 'emulated_hue' + +_LOGGER = logging.getLogger(__name__) + +CONF_HOST_IP = 'host_ip' +CONF_LISTEN_PORT = 'listen_port' +CONF_OFF_MAPS_TO_ON_DOMAINS = 'off_maps_to_on_domains' +CONF_EXPOSE_BY_DEFAULT = 'expose_by_default' +CONF_EXPOSED_DOMAINS = 'exposed_domains' +CONF_TYPE = 'type' + +TYPE_ALEXA = 'alexa' +TYPE_GOOGLE = 'google_home' + +DEFAULT_LISTEN_PORT = 8300 +DEFAULT_OFF_MAPS_TO_ON_DOMAINS = ['script', 'scene'] +DEFAULT_EXPOSE_BY_DEFAULT = True +DEFAULT_EXPOSED_DOMAINS = [ + 'switch', 'light', 'group', 'input_boolean', 'media_player', 'fan' +] +DEFAULT_TYPE = TYPE_ALEXA + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Optional(CONF_HOST_IP): cv.string, + vol.Optional(CONF_LISTEN_PORT, default=DEFAULT_LISTEN_PORT): + vol.All(vol.Coerce(int), vol.Range(min=1, max=65535)), + vol.Optional(CONF_OFF_MAPS_TO_ON_DOMAINS): cv.ensure_list, + vol.Optional(CONF_EXPOSE_BY_DEFAULT): cv.boolean, + vol.Optional(CONF_EXPOSED_DOMAINS): cv.ensure_list, + vol.Optional(CONF_TYPE, default=DEFAULT_TYPE): + vol.Any(TYPE_ALEXA, TYPE_GOOGLE) + }) +}, extra=vol.ALLOW_EXTRA) + +ATTR_EMULATED_HUE = 'emulated_hue' + + +def setup(hass, yaml_config): + """Activate the emulated_hue component.""" + config = Config(yaml_config.get(DOMAIN, {})) + + server = HomeAssistantWSGI( + hass, + development=False, + server_host=config.host_ip_addr, + server_port=config.listen_port, + api_password=None, + ssl_certificate=None, + ssl_key=None, + cors_origins=None, + use_x_forwarded_for=False, + trusted_networks=[], + login_threshold=0, + is_ban_enabled=False + ) + + server.register_view(DescriptionXmlView(config)) + server.register_view(HueUsernameView) + server.register_view(HueAllLightsStateView(config)) + server.register_view(HueOneLightStateView(config)) + server.register_view(HueOneLightChangeView(config)) + + upnp_listener = UPNPResponderThread( + config.host_ip_addr, config.listen_port) + + @asyncio.coroutine + def stop_emulated_hue_bridge(event): + """Stop the emulated hue bridge.""" + upnp_listener.stop() + yield from server.stop() + + @asyncio.coroutine + def start_emulated_hue_bridge(event): + """Start the emulated hue bridge.""" + upnp_listener.start() + yield from server.start() + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, + stop_emulated_hue_bridge) + + hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_emulated_hue_bridge) + + return True + + +class Config(object): + """Holds configuration variables for the emulated hue bridge.""" + + def __init__(self, conf): + """Initialize the instance.""" + self.type = conf.get(CONF_TYPE) + self.numbers = {} + self.cached_states = {} + + # Get the IP address that will be passed to the Echo during discovery + self.host_ip_addr = conf.get(CONF_HOST_IP) + if self.host_ip_addr is None: + self.host_ip_addr = util.get_local_ip() + _LOGGER.warning( + "Listen IP address not specified, auto-detected address is %s", + self.host_ip_addr) + + # Get the port that the Hue bridge will listen on + self.listen_port = conf.get(CONF_LISTEN_PORT) + if not isinstance(self.listen_port, int): + self.listen_port = DEFAULT_LISTEN_PORT + _LOGGER.warning( + "Listen port not specified, defaulting to %s", + self.listen_port) + + if self.type == TYPE_GOOGLE and self.listen_port != 80: + _LOGGER.warning('When targetting Google Home, listening port has ' + 'to be port 80') + + # Get domains that cause both "on" and "off" commands to map to "on" + # This is primarily useful for things like scenes or scripts, which + # don't really have a concept of being off + self.off_maps_to_on_domains = conf.get(CONF_OFF_MAPS_TO_ON_DOMAINS) + if not isinstance(self.off_maps_to_on_domains, list): + self.off_maps_to_on_domains = DEFAULT_OFF_MAPS_TO_ON_DOMAINS + + # Get whether or not entities should be exposed by default, or if only + # explicitly marked ones will be exposed + self.expose_by_default = conf.get( + CONF_EXPOSE_BY_DEFAULT, DEFAULT_EXPOSE_BY_DEFAULT) + + # Get domains that are exposed by default when expose_by_default is + # True + self.exposed_domains = conf.get( + CONF_EXPOSED_DOMAINS, DEFAULT_EXPOSED_DOMAINS) + + def entity_id_to_number(self, entity_id): + """Get a unique number for the entity id.""" + if self.type == TYPE_ALEXA: + return entity_id + + # Google Home + for number, ent_id in self.numbers.items(): + if entity_id == ent_id: + return number + + number = str(len(self.numbers) + 1) + self.numbers[number] = entity_id + return number + + def number_to_entity_id(self, number): + """Convert unique number to entity id.""" + if self.type == TYPE_ALEXA: + return number + + # Google Home + assert isinstance(number, str) + return self.numbers.get(number) + + def is_entity_exposed(self, entity): + """Determine if an entity should be exposed on the emulated bridge. + + Async friendly. + """ + if entity.attributes.get('view') is not None: + # Ignore entities that are views + return False + + domain = entity.domain.lower() + explicit_expose = entity.attributes.get(ATTR_EMULATED_HUE, None) + + domain_exposed_by_default = \ + self.expose_by_default and domain in self.exposed_domains + + # Expose an entity if the entity's domain is exposed by default and + # the configuration doesn't explicitly exclude it from being + # exposed, or if the entity is explicitly exposed + is_default_exposed = \ + domain_exposed_by_default and explicit_expose is not False + + return is_default_exposed or explicit_expose diff --git a/homeassistant/components/emulated_hue/hue_api.py b/homeassistant/components/emulated_hue/hue_api.py new file mode 100644 index 00000000000..ed06da9495b --- /dev/null +++ b/homeassistant/components/emulated_hue/hue_api.py @@ -0,0 +1,275 @@ +"""Provides a Hue API to control Home Assistant.""" +import asyncio +import logging + +from aiohttp import web + +from homeassistant import core +from homeassistant.const import ( + ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON, + STATE_ON, STATE_OFF, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, +) +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, ATTR_SUPPORTED_FEATURES, SUPPORT_BRIGHTNESS +) +from homeassistant.components.http import HomeAssistantView + +_LOGGER = logging.getLogger(__name__) + +ATTR_EMULATED_HUE = 'emulated_hue' +ATTR_EMULATED_HUE_NAME = 'emulated_hue_name' + +HUE_API_STATE_ON = 'on' +HUE_API_STATE_BRI = 'bri' + + +class HueUsernameView(HomeAssistantView): + """Handle requests to create a username for the emulated hue bridge.""" + + url = '/api' + name = 'emulated_hue:api:create_username' + extra_urls = ['/api/'] + requires_auth = False + + @asyncio.coroutine + def post(self, request): + """Handle a POST request.""" + try: + data = yield from request.json() + except ValueError: + return self.json_message('Invalid JSON', HTTP_BAD_REQUEST) + + if 'devicetype' not in data: + return self.json_message('devicetype not specified', + HTTP_BAD_REQUEST) + + return self.json([{'success': {'username': '12345678901234567890'}}]) + + +class HueAllLightsStateView(HomeAssistantView): + """Handle requests for getting and setting info about entities.""" + + url = '/api/{username}/lights' + name = 'emulated_hue:lights:state' + requires_auth = False + + def __init__(self, config): + """Initialize the instance of the view.""" + self.config = config + + @core.callback + def get(self, request, username): + """Process a request to get the list of available lights.""" + hass = request.app['hass'] + json_response = {} + + for entity in hass.states.async_all(): + if self.config.is_entity_exposed(entity): + number = self.config.entity_id_to_number(entity.entity_id) + json_response[number] = entity_to_json(entity) + + return self.json(json_response) + + +class HueOneLightStateView(HomeAssistantView): + """Handle requests for getting and setting info about entities.""" + + url = '/api/{username}/lights/{entity_id}' + name = 'emulated_hue:light:state' + requires_auth = False + + def __init__(self, config): + """Initialize the instance of the view.""" + self.config = config + + @core.callback + def get(self, request, username, entity_id=None): + """Process a request to get the state of an individual light.""" + hass = request.app['hass'] + entity_id = self.config.number_to_entity_id(entity_id) + entity = hass.states.get(entity_id) + + if entity is None: + _LOGGER.error('Entity not found: %s', entity_id) + return web.Response(text="Entity not found", status=404) + + if not self.config.is_entity_exposed(entity): + _LOGGER.error('Entity not exposed: %s', entity_id) + return web.Response(text="Entity not exposed", status=404) + + cached_state = self.config.cached_states.get(entity_id, None) + + if cached_state is None: + final_state = entity.state == STATE_ON + final_brightness = entity.attributes.get( + ATTR_BRIGHTNESS, 255 if final_state else 0) + else: + final_state, final_brightness = cached_state + + json_response = entity_to_json(entity, final_state, final_brightness) + + return self.json(json_response) + + +class HueOneLightChangeView(HomeAssistantView): + """Handle requests for getting and setting info about entities.""" + + url = '/api/{username}/lights/{entity_number}/state' + name = 'emulated_hue:light:state' + requires_auth = False + + def __init__(self, config): + """Initialize the instance of the view.""" + self.config = config + + @asyncio.coroutine + def put(self, request, username, entity_number): + """Process a request to set the state of an individual light.""" + config = self.config + hass = request.app['hass'] + entity_id = config.number_to_entity_id(entity_number) + + if entity_id is None: + _LOGGER.error('Unknown entity number: %s', entity_number) + return self.json_message('Entity not found', HTTP_NOT_FOUND) + + entity = hass.states.get(entity_id) + + if entity is None: + _LOGGER.error('Entity not found: %s', entity_id) + return self.json_message('Entity not found', HTTP_NOT_FOUND) + + if not config.is_entity_exposed(entity): + _LOGGER.error('Entity not exposed: %s', entity_id) + return web.Response(text="Entity not exposed", status=404) + + try: + request_json = yield from request.json() + except ValueError: + _LOGGER.error('Received invalid json') + return self.json_message('Invalid JSON', HTTP_BAD_REQUEST) + + # Parse the request into requested "on" status and brightness + parsed = parse_hue_api_put_light_body(request_json, entity) + + if parsed is None: + _LOGGER.error('Unable to parse data: %s', request_json) + return web.Response(text="Bad request", status=400) + + result, brightness = parsed + + # Convert the resulting "on" status into the service we need to call + service = SERVICE_TURN_ON if result else SERVICE_TURN_OFF + + # Construct what we need to send to the service + data = {ATTR_ENTITY_ID: entity_id} + + # If the requested entity is a script add some variables + if entity.domain == "script": + data['variables'] = { + 'requested_state': STATE_ON if result else STATE_OFF + } + + if brightness is not None: + data['variables']['requested_level'] = brightness + + elif brightness is not None: + data[ATTR_BRIGHTNESS] = brightness + + if entity.domain in config.off_maps_to_on_domains: + # Map the off command to on + service = SERVICE_TURN_ON + + # Caching is required because things like scripts and scenes won't + # report as "off" to Alexa if an "off" command is received, because + # they'll map to "on". Thus, instead of reporting its actual + # status, we report what Alexa will want to see, which is the same + # as the actual requested command. + config.cached_states[entity_id] = (result, brightness) + + # Perform the requested action + yield from hass.services.async_call(core.DOMAIN, service, data, + blocking=True) + + json_response = \ + [create_hue_success_response(entity_id, HUE_API_STATE_ON, result)] + + if brightness is not None: + json_response.append(create_hue_success_response( + entity_id, HUE_API_STATE_BRI, brightness)) + + return self.json(json_response) + + +def parse_hue_api_put_light_body(request_json, entity): + """Parse the body of a request to change the state of a light.""" + if HUE_API_STATE_ON in request_json: + if not isinstance(request_json[HUE_API_STATE_ON], bool): + return None + + if request_json['on']: + # Echo requested device be turned on + brightness = None + report_brightness = False + result = True + else: + # Echo requested device be turned off + brightness = None + report_brightness = False + result = False + + if HUE_API_STATE_BRI in request_json: + # Make sure the entity actually supports brightness + entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) + + if (entity_features & SUPPORT_BRIGHTNESS) == SUPPORT_BRIGHTNESS: + try: + # Clamp brightness from 0 to 255 + brightness = \ + max(0, min(int(request_json[HUE_API_STATE_BRI]), 255)) + except ValueError: + return None + + report_brightness = True + result = (brightness > 0) + elif entity.domain.lower() == "script": + # Convert 0-255 to 0-100 + level = int(request_json[HUE_API_STATE_BRI]) / 255 * 100 + + brightness = round(level) + report_brightness = True + result = True + + return (result, brightness) if report_brightness else (result, None) + + +def entity_to_json(entity, is_on=None, brightness=None): + """Convert an entity to its Hue bridge JSON representation.""" + if is_on is None: + is_on = entity.state == STATE_ON + + if brightness is None: + brightness = 255 if is_on else 0 + + name = entity.attributes.get( + ATTR_EMULATED_HUE_NAME, entity.attributes[ATTR_FRIENDLY_NAME]) + + return { + 'state': + { + HUE_API_STATE_ON: is_on, + HUE_API_STATE_BRI: brightness, + 'reachable': True + }, + 'type': 'Dimmable light', + 'name': name, + 'modelid': 'HASS123', + 'uniqueid': entity.entity_id, + 'swversion': '123' + } + + +def create_hue_success_response(entity_id, attr, value): + """Create a success response for an attribute set on a light.""" + success_key = '/lights/{}/state/{}'.format(entity_id, attr) + return {'success': {success_key: value}} diff --git a/homeassistant/components/emulated_hue/upnp.py b/homeassistant/components/emulated_hue/upnp.py new file mode 100644 index 00000000000..f81a8c1b68d --- /dev/null +++ b/homeassistant/components/emulated_hue/upnp.py @@ -0,0 +1,166 @@ +"""Provides a UPNP discovery method that mimicks Hue hubs.""" +import threading +import socket +import logging +import os +import select + +from aiohttp import web + +from homeassistant import core +from homeassistant.components.http import HomeAssistantView + +_LOGGER = logging.getLogger(__name__) + + +class DescriptionXmlView(HomeAssistantView): + """Handles requests for the description.xml file.""" + + url = '/description.xml' + name = 'description:xml' + requires_auth = False + + def __init__(self, config): + """Initialize the instance of the view.""" + self.config = config + + @core.callback + def get(self, request): + """Handle a GET request.""" + xml_template = """ + + +1 +0 + +http://{0}:{1}/ + +urn:schemas-upnp-org:device:Basic:1 +HASS Bridge ({0}) +Royal Philips Electronics +http://www.philips.com +Philips hue Personal Wireless Lighting +Philips hue bridge 2015 +BSB002 +http://www.meethue.com +1234 +uuid:2f402f80-da50-11e1-9b23-001788255acc + + +""" + + resp_text = xml_template.format( + self.config.host_ip_addr, self.config.listen_port) + + return web.Response(text=resp_text, content_type='text/xml') + + +class UPNPResponderThread(threading.Thread): + """Handle responding to UPNP/SSDP discovery requests.""" + + _interrupted = False + + def __init__(self, host_ip_addr, listen_port): + """Initialize the class.""" + threading.Thread.__init__(self) + + self.host_ip_addr = host_ip_addr + self.listen_port = listen_port + + # Note that the double newline at the end of + # this string is required per the SSDP spec + resp_template = """HTTP/1.1 200 OK +CACHE-CONTROL: max-age=60 +EXT: +LOCATION: http://{0}:{1}/description.xml +SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/0.1 +ST: urn:schemas-upnp-org:device:basic:1 +USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1 + +""" + + self.upnp_response = resp_template.format(host_ip_addr, listen_port) \ + .replace("\n", "\r\n") \ + .encode('utf-8') + + # Set up a pipe for signaling to the receiver that it's time to + # shutdown. Essentially, we place the SSDP socket into nonblocking + # mode and use select() to wait for data to arrive on either the SSDP + # socket or the pipe. If data arrives on either one, select() returns + # and tells us which filenos have data ready to read. + # + # When we want to stop the responder, we write data to the pipe, which + # causes the select() to return and indicate that said pipe has data + # ready to be read, which indicates to us that the responder needs to + # be shutdown. + self._interrupted_read_pipe, self._interrupted_write_pipe = os.pipe() + + def run(self): + """Run the server.""" + # Listen for UDP port 1900 packets sent to SSDP multicast address + ssdp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + ssdp_socket.setblocking(False) + + # Required for receiving multicast + ssdp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + ssdp_socket.setsockopt( + socket.SOL_IP, + socket.IP_MULTICAST_IF, + socket.inet_aton(self.host_ip_addr)) + + ssdp_socket.setsockopt( + socket.SOL_IP, + socket.IP_ADD_MEMBERSHIP, + socket.inet_aton("239.255.255.250") + + socket.inet_aton(self.host_ip_addr)) + + ssdp_socket.bind(("239.255.255.250", 1900)) + + while True: + if self._interrupted: + clean_socket_close(ssdp_socket) + return + + try: + read, _, _ = select.select( + [self._interrupted_read_pipe, ssdp_socket], [], + [ssdp_socket]) + + if self._interrupted_read_pipe in read: + # Implies self._interrupted is True + clean_socket_close(ssdp_socket) + return + elif ssdp_socket in read: + data, addr = ssdp_socket.recvfrom(1024) + else: + continue + except socket.error as ex: + if self._interrupted: + clean_socket_close(ssdp_socket) + return + + _LOGGER.error("UPNP Responder socket exception occured: %s", + ex.__str__) + + if "M-SEARCH" in data.decode('utf-8'): + # SSDP M-SEARCH method received, respond to it with our info + resp_socket = socket.socket( + socket.AF_INET, socket.SOCK_DGRAM) + + resp_socket.sendto(self.upnp_response, addr) + resp_socket.close() + + def stop(self): + """Stop the server.""" + # Request for server + self._interrupted = True + os.write(self._interrupted_write_pipe, bytes([0])) + self.join() + + +def clean_socket_close(sock): + """Close a socket connection and logs its closure.""" + _LOGGER.info("UPNP responder shutting down.") + + sock.close() diff --git a/tests/components/emulated_hue/__init__.py b/tests/components/emulated_hue/__init__.py new file mode 100644 index 00000000000..b13b95a080a --- /dev/null +++ b/tests/components/emulated_hue/__init__.py @@ -0,0 +1 @@ +"""Tests for emulated_hue.""" diff --git a/tests/components/test_emulated_hue.py b/tests/components/emulated_hue/test_hue_api.py old mode 100755 new mode 100644 similarity index 78% rename from tests/components/test_emulated_hue.py rename to tests/components/emulated_hue/test_hue_api.py index 7bb8da09e47..9cee27f570f --- a/tests/components/test_emulated_hue.py +++ b/tests/components/emulated_hue/test_hue_api.py @@ -1,429 +1,355 @@ -"""The tests for the emulated Hue component.""" -import json - -import unittest -import requests - -from homeassistant import bootstrap, const, core -import homeassistant.components as core_components -from homeassistant.components import emulated_hue, http, light, script -from homeassistant.const import STATE_ON, STATE_OFF -from homeassistant.components.emulated_hue import ( - HUE_API_STATE_ON, HUE_API_STATE_BRI) -from homeassistant.util.async import run_coroutine_threadsafe - -from tests.common import get_test_instance_port, get_test_home_assistant - -HTTP_SERVER_PORT = get_test_instance_port() -BRIDGE_SERVER_PORT = get_test_instance_port() - -BRIDGE_URL_BASE = 'http://127.0.0.1:{}'.format(BRIDGE_SERVER_PORT) + '{}' -JSON_HEADERS = {const.HTTP_HEADER_CONTENT_TYPE: const.CONTENT_TYPE_JSON} - - -def setup_hass_instance(emulated_hue_config): - """Set up the Home Assistant instance to test.""" - hass = get_test_home_assistant() - - # We need to do this to get access to homeassistant/turn_(on,off) - run_coroutine_threadsafe( - core_components.async_setup(hass, {core.DOMAIN: {}}), hass.loop - ).result() - - bootstrap.setup_component( - hass, http.DOMAIN, - {http.DOMAIN: {http.CONF_SERVER_PORT: HTTP_SERVER_PORT}}) - - bootstrap.setup_component(hass, emulated_hue.DOMAIN, emulated_hue_config) - - return hass - - -def start_hass_instance(hass): - """Start the Home Assistant instance to test.""" - hass.start() - - -class TestEmulatedHue(unittest.TestCase): - """Test the emulated Hue component.""" - - hass = None - - @classmethod - def setUpClass(cls): - """Setup the class.""" - cls.hass = setup_hass_instance({ - emulated_hue.DOMAIN: { - emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT - }}) - - start_hass_instance(cls.hass) - - @classmethod - def tearDownClass(cls): - """Stop the class.""" - cls.hass.stop() - - def test_description_xml(self): - """Test the description.""" - import xml.etree.ElementTree as ET - - result = requests.get( - BRIDGE_URL_BASE.format('/description.xml'), timeout=5) - - self.assertEqual(result.status_code, 200) - self.assertTrue('text/xml' in result.headers['content-type']) - - # Make sure the XML is parsable - # pylint: disable=bare-except - try: - ET.fromstring(result.text) - except: - self.fail('description.xml is not valid XML!') - - def test_create_username(self): - """Test the creation of an username.""" - request_json = {'devicetype': 'my_device'} - - result = requests.post( - BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json), - timeout=5) - - self.assertEqual(result.status_code, 200) - self.assertTrue('application/json' in result.headers['content-type']) - - resp_json = result.json() - success_json = resp_json[0] - - self.assertTrue('success' in success_json) - self.assertTrue('username' in success_json['success']) - - def test_valid_username_request(self): - """Test request with a valid username.""" - request_json = {'invalid_key': 'my_device'} - - result = requests.post( - BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json), - timeout=5) - - self.assertEqual(result.status_code, 400) - - -class TestEmulatedHueExposedByDefault(unittest.TestCase): - """Test class for emulated hue component.""" - - @classmethod - def setUpClass(cls): - """Setup the class.""" - cls.hass = setup_hass_instance({ - emulated_hue.DOMAIN: { - emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT, - emulated_hue.CONF_EXPOSE_BY_DEFAULT: True - } - }) - - bootstrap.setup_component(cls.hass, light.DOMAIN, { - 'light': [ - { - 'platform': 'demo', - } - ] - }) - - bootstrap.setup_component(cls.hass, script.DOMAIN, { - 'script': { - 'set_kitchen_light': { - 'sequence': [ - { - 'service_template': - "light.turn_{{ requested_state }}", - 'data_template': { - 'entity_id': 'light.kitchen_lights', - 'brightness': "{{ requested_level }}" - } - } - ] - } - } - }) - - start_hass_instance(cls.hass) - - # Kitchen light is explicitly excluded from being exposed - kitchen_light_entity = cls.hass.states.get('light.kitchen_lights') - attrs = dict(kitchen_light_entity.attributes) - attrs[emulated_hue.ATTR_EMULATED_HUE] = False - cls.hass.states.set( - kitchen_light_entity.entity_id, kitchen_light_entity.state, - attributes=attrs) - - # Expose the script - script_entity = cls.hass.states.get('script.set_kitchen_light') - attrs = dict(script_entity.attributes) - attrs[emulated_hue.ATTR_EMULATED_HUE] = True - cls.hass.states.set( - script_entity.entity_id, script_entity.state, attributes=attrs - ) - - @classmethod - def tearDownClass(cls): - """Stop the class.""" - cls.hass.stop() - - def test_discover_lights(self): - """Test the discovery of lights.""" - result = requests.get( - BRIDGE_URL_BASE.format('/api/username/lights'), timeout=5) - - self.assertEqual(result.status_code, 200) - self.assertTrue('application/json' in result.headers['content-type']) - - result_json = result.json() - - # Make sure the lights we added to the config are there - self.assertTrue('light.ceiling_lights' in result_json) - self.assertTrue('light.bed_light' in result_json) - self.assertTrue('script.set_kitchen_light' in result_json) - self.assertTrue('light.kitchen_lights' not in result_json) - - def test_get_light_state(self): - """Test the getting of light state.""" - # Turn office light on and set to 127 brightness - self.hass.services.call( - light.DOMAIN, const.SERVICE_TURN_ON, - { - const.ATTR_ENTITY_ID: 'light.ceiling_lights', - light.ATTR_BRIGHTNESS: 127 - }, - blocking=True) - - office_json = self.perform_get_light_state('light.ceiling_lights', 200) - - self.assertEqual(office_json['state'][HUE_API_STATE_ON], True) - self.assertEqual(office_json['state'][HUE_API_STATE_BRI], 127) - - # Turn bedroom light off - self.hass.services.call( - light.DOMAIN, const.SERVICE_TURN_OFF, - { - const.ATTR_ENTITY_ID: 'light.bed_light' - }, - blocking=True) - - bedroom_json = self.perform_get_light_state('light.bed_light', 200) - - self.assertEqual(bedroom_json['state'][HUE_API_STATE_ON], False) - self.assertEqual(bedroom_json['state'][HUE_API_STATE_BRI], 0) - - # Make sure kitchen light isn't accessible - kitchen_url = '/api/username/lights/{}'.format('light.kitchen_lights') - kitchen_result = requests.get( - BRIDGE_URL_BASE.format(kitchen_url), timeout=5) - - self.assertEqual(kitchen_result.status_code, 404) - - def test_put_light_state(self): - """Test the seeting of light states.""" - self.perform_put_test_on_ceiling_lights() - - # Turn the bedroom light on first - self.hass.services.call( - light.DOMAIN, const.SERVICE_TURN_ON, - {const.ATTR_ENTITY_ID: 'light.bed_light', - light.ATTR_BRIGHTNESS: 153}, - blocking=True) - - bed_light = self.hass.states.get('light.bed_light') - self.assertEqual(bed_light.state, STATE_ON) - self.assertEqual(bed_light.attributes[light.ATTR_BRIGHTNESS], 153) - - # Go through the API to turn it off - bedroom_result = self.perform_put_light_state( - 'light.bed_light', False) - - bedroom_result_json = bedroom_result.json() - - self.assertEqual(bedroom_result.status_code, 200) - self.assertTrue( - 'application/json' in bedroom_result.headers['content-type']) - - self.assertEqual(len(bedroom_result_json), 1) - - # Check to make sure the state changed - bed_light = self.hass.states.get('light.bed_light') - self.assertEqual(bed_light.state, STATE_OFF) - - # Make sure we can't change the kitchen light state - kitchen_result = self.perform_put_light_state( - 'light.kitchen_light', True) - self.assertEqual(kitchen_result.status_code, 404) - - def test_put_light_state_script(self): - """Test the setting of script variables.""" - # Turn the kitchen light off first - self.hass.services.call( - light.DOMAIN, const.SERVICE_TURN_OFF, - {const.ATTR_ENTITY_ID: 'light.kitchen_lights'}, - blocking=True) - - # Emulated hue converts 0-100% to 0-255. - level = 23 - brightness = round(level * 255 / 100) - - script_result = self.perform_put_light_state( - 'script.set_kitchen_light', True, brightness) - - script_result_json = script_result.json() - - self.assertEqual(script_result.status_code, 200) - self.assertEqual(len(script_result_json), 2) - - # Wait until script is complete before continuing - self.hass.block_till_done() - - kitchen_light = self.hass.states.get('light.kitchen_lights') - self.assertEqual(kitchen_light.state, 'on') - self.assertEqual( - kitchen_light.attributes[light.ATTR_BRIGHTNESS], - level) - - # pylint: disable=invalid-name - def test_put_with_form_urlencoded_content_type(self): - """Test the form with urlencoded content.""" - # Needed for Alexa - self.perform_put_test_on_ceiling_lights( - 'application/x-www-form-urlencoded') - - # Make sure we fail gracefully when we can't parse the data - data = {'key1': 'value1', 'key2': 'value2'} - result = requests.put( - BRIDGE_URL_BASE.format( - '/api/username/lights/{}/state'.format( - 'light.ceiling_lights')), data=data) - - self.assertEqual(result.status_code, 400) - - def test_entity_not_found(self): - """Test for entity which are not found.""" - result = requests.get( - BRIDGE_URL_BASE.format( - '/api/username/lights/{}'.format("not.existant_entity")), - timeout=5) - - self.assertEqual(result.status_code, 404) - - result = requests.put( - BRIDGE_URL_BASE.format( - '/api/username/lights/{}/state'.format("non.existant_entity")), - timeout=5) - - self.assertEqual(result.status_code, 404) - - def test_allowed_methods(self): - """Test the allowed methods.""" - result = requests.get( - BRIDGE_URL_BASE.format( - '/api/username/lights/{}/state'.format( - "light.ceiling_lights"))) - - self.assertEqual(result.status_code, 405) - - result = requests.put( - BRIDGE_URL_BASE.format( - '/api/username/lights/{}'.format("light.ceiling_lights")), - data={'key1': 'value1'}) - - self.assertEqual(result.status_code, 405) - - result = requests.put( - BRIDGE_URL_BASE.format('/api/username/lights'), - data={'key1': 'value1'}) - - self.assertEqual(result.status_code, 405) - - def test_proper_put_state_request(self): - """Test the request to set the state.""" - # Test proper on value parsing - result = requests.put( - BRIDGE_URL_BASE.format( - '/api/username/lights/{}/state'.format( - 'light.ceiling_lights')), - data=json.dumps({HUE_API_STATE_ON: 1234})) - - self.assertEqual(result.status_code, 400) - - # Test proper brightness value parsing - result = requests.put( - BRIDGE_URL_BASE.format( - '/api/username/lights/{}/state'.format( - 'light.ceiling_lights')), data=json.dumps({ - HUE_API_STATE_ON: True, - HUE_API_STATE_BRI: 'Hello world!' - })) - - self.assertEqual(result.status_code, 400) - - # pylint: disable=invalid-name - def perform_put_test_on_ceiling_lights(self, - content_type='application/json'): - """Test the setting of a light.""" - # Turn the office light off first - self.hass.services.call( - light.DOMAIN, const.SERVICE_TURN_OFF, - {const.ATTR_ENTITY_ID: 'light.ceiling_lights'}, - blocking=True) - - ceiling_lights = self.hass.states.get('light.ceiling_lights') - self.assertEqual(ceiling_lights.state, STATE_OFF) - - # Go through the API to turn it on - office_result = self.perform_put_light_state( - 'light.ceiling_lights', True, 56, content_type) - - office_result_json = office_result.json() - - self.assertEqual(office_result.status_code, 200) - self.assertTrue( - 'application/json' in office_result.headers['content-type']) - - self.assertEqual(len(office_result_json), 2) - - # Check to make sure the state changed - ceiling_lights = self.hass.states.get('light.ceiling_lights') - self.assertEqual(ceiling_lights.state, STATE_ON) - self.assertEqual(ceiling_lights.attributes[light.ATTR_BRIGHTNESS], 56) - - def perform_get_light_state(self, entity_id, expected_status): - """Test the gettting of a light state.""" - result = requests.get( - BRIDGE_URL_BASE.format( - '/api/username/lights/{}'.format(entity_id)), timeout=5) - - self.assertEqual(result.status_code, expected_status) - - if expected_status == 200: - self.assertTrue( - 'application/json' in result.headers['content-type']) - - return result.json() - - return None - - # pylint: disable=no-self-use - def perform_put_light_state(self, entity_id, is_on, brightness=None, - content_type='application/json'): - """Test the setting of a light state.""" - url = BRIDGE_URL_BASE.format( - '/api/username/lights/{}/state'.format(entity_id)) - - req_headers = {'Content-Type': content_type} - - data = {HUE_API_STATE_ON: is_on} - - if brightness is not None: - data[HUE_API_STATE_BRI] = brightness - - result = requests.put( - url, data=json.dumps(data), timeout=5, headers=req_headers) - - return result +"""The tests for the emulated Hue component.""" +import json + +import unittest +from unittest.mock import patch +import requests + +from homeassistant import bootstrap, const, core +import homeassistant.components as core_components +from homeassistant.components import emulated_hue, http, light, script +from homeassistant.const import STATE_ON, STATE_OFF +from homeassistant.components.emulated_hue.hue_api import ( + HUE_API_STATE_ON, HUE_API_STATE_BRI) +from homeassistant.util.async import run_coroutine_threadsafe + +from tests.common import get_test_instance_port, get_test_home_assistant + +HTTP_SERVER_PORT = get_test_instance_port() +BRIDGE_SERVER_PORT = get_test_instance_port() + +BRIDGE_URL_BASE = 'http://127.0.0.1:{}'.format(BRIDGE_SERVER_PORT) + '{}' +JSON_HEADERS = {const.HTTP_HEADER_CONTENT_TYPE: const.CONTENT_TYPE_JSON} + + +class TestEmulatedHueExposedByDefault(unittest.TestCase): + """Test class for emulated hue component.""" + + @classmethod + def setUpClass(cls): + """Setup the class.""" + cls.hass = hass = get_test_home_assistant() + + # We need to do this to get access to homeassistant/turn_(on,off) + run_coroutine_threadsafe( + core_components.async_setup(hass, {core.DOMAIN: {}}), hass.loop + ).result() + + bootstrap.setup_component( + hass, http.DOMAIN, + {http.DOMAIN: {http.CONF_SERVER_PORT: HTTP_SERVER_PORT}}) + + with patch('homeassistant.components' + '.emulated_hue.UPNPResponderThread'): + bootstrap.setup_component(hass, emulated_hue.DOMAIN, { + emulated_hue.DOMAIN: { + emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT, + emulated_hue.CONF_EXPOSE_BY_DEFAULT: True + } + }) + + bootstrap.setup_component(cls.hass, light.DOMAIN, { + 'light': [ + { + 'platform': 'demo', + } + ] + }) + + bootstrap.setup_component(cls.hass, script.DOMAIN, { + 'script': { + 'set_kitchen_light': { + 'sequence': [ + { + 'service_template': + "light.turn_{{ requested_state }}", + 'data_template': { + 'entity_id': 'light.kitchen_lights', + 'brightness': "{{ requested_level }}" + } + } + ] + } + } + }) + + cls.hass.start() + + # Kitchen light is explicitly excluded from being exposed + kitchen_light_entity = cls.hass.states.get('light.kitchen_lights') + attrs = dict(kitchen_light_entity.attributes) + attrs[emulated_hue.ATTR_EMULATED_HUE] = False + cls.hass.states.set( + kitchen_light_entity.entity_id, kitchen_light_entity.state, + attributes=attrs) + + # Expose the script + script_entity = cls.hass.states.get('script.set_kitchen_light') + attrs = dict(script_entity.attributes) + attrs[emulated_hue.ATTR_EMULATED_HUE] = True + cls.hass.states.set( + script_entity.entity_id, script_entity.state, attributes=attrs + ) + + @classmethod + def tearDownClass(cls): + """Stop the class.""" + cls.hass.stop() + + def test_discover_lights(self): + """Test the discovery of lights.""" + result = requests.get( + BRIDGE_URL_BASE.format('/api/username/lights'), timeout=5) + + self.assertEqual(result.status_code, 200) + self.assertTrue('application/json' in result.headers['content-type']) + + result_json = result.json() + + # Make sure the lights we added to the config are there + self.assertTrue('light.ceiling_lights' in result_json) + self.assertTrue('light.bed_light' in result_json) + self.assertTrue('script.set_kitchen_light' in result_json) + self.assertTrue('light.kitchen_lights' not in result_json) + + def test_get_light_state(self): + """Test the getting of light state.""" + # Turn office light on and set to 127 brightness + self.hass.services.call( + light.DOMAIN, const.SERVICE_TURN_ON, + { + const.ATTR_ENTITY_ID: 'light.ceiling_lights', + light.ATTR_BRIGHTNESS: 127 + }, + blocking=True) + + office_json = self.perform_get_light_state('light.ceiling_lights', 200) + + self.assertEqual(office_json['state'][HUE_API_STATE_ON], True) + self.assertEqual(office_json['state'][HUE_API_STATE_BRI], 127) + + # Turn bedroom light off + self.hass.services.call( + light.DOMAIN, const.SERVICE_TURN_OFF, + { + const.ATTR_ENTITY_ID: 'light.bed_light' + }, + blocking=True) + + bedroom_json = self.perform_get_light_state('light.bed_light', 200) + + self.assertEqual(bedroom_json['state'][HUE_API_STATE_ON], False) + self.assertEqual(bedroom_json['state'][HUE_API_STATE_BRI], 0) + + # Make sure kitchen light isn't accessible + kitchen_url = '/api/username/lights/{}'.format('light.kitchen_lights') + kitchen_result = requests.get( + BRIDGE_URL_BASE.format(kitchen_url), timeout=5) + + self.assertEqual(kitchen_result.status_code, 404) + + def test_put_light_state(self): + """Test the seeting of light states.""" + self.perform_put_test_on_ceiling_lights() + + # Turn the bedroom light on first + self.hass.services.call( + light.DOMAIN, const.SERVICE_TURN_ON, + {const.ATTR_ENTITY_ID: 'light.bed_light', + light.ATTR_BRIGHTNESS: 153}, + blocking=True) + + bed_light = self.hass.states.get('light.bed_light') + self.assertEqual(bed_light.state, STATE_ON) + self.assertEqual(bed_light.attributes[light.ATTR_BRIGHTNESS], 153) + + # Go through the API to turn it off + bedroom_result = self.perform_put_light_state( + 'light.bed_light', False) + + bedroom_result_json = bedroom_result.json() + + self.assertEqual(bedroom_result.status_code, 200) + self.assertTrue( + 'application/json' in bedroom_result.headers['content-type']) + + self.assertEqual(len(bedroom_result_json), 1) + + # Check to make sure the state changed + bed_light = self.hass.states.get('light.bed_light') + self.assertEqual(bed_light.state, STATE_OFF) + + # Make sure we can't change the kitchen light state + kitchen_result = self.perform_put_light_state( + 'light.kitchen_light', True) + self.assertEqual(kitchen_result.status_code, 404) + + def test_put_light_state_script(self): + """Test the setting of script variables.""" + # Turn the kitchen light off first + self.hass.services.call( + light.DOMAIN, const.SERVICE_TURN_OFF, + {const.ATTR_ENTITY_ID: 'light.kitchen_lights'}, + blocking=True) + + # Emulated hue converts 0-100% to 0-255. + level = 23 + brightness = round(level * 255 / 100) + + script_result = self.perform_put_light_state( + 'script.set_kitchen_light', True, brightness) + + script_result_json = script_result.json() + + self.assertEqual(script_result.status_code, 200) + self.assertEqual(len(script_result_json), 2) + + # Wait until script is complete before continuing + self.hass.block_till_done() + + kitchen_light = self.hass.states.get('light.kitchen_lights') + self.assertEqual(kitchen_light.state, 'on') + self.assertEqual( + kitchen_light.attributes[light.ATTR_BRIGHTNESS], + level) + + # pylint: disable=invalid-name + def test_put_with_form_urlencoded_content_type(self): + """Test the form with urlencoded content.""" + # Needed for Alexa + self.perform_put_test_on_ceiling_lights( + 'application/x-www-form-urlencoded') + + # Make sure we fail gracefully when we can't parse the data + data = {'key1': 'value1', 'key2': 'value2'} + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format( + 'light.ceiling_lights')), data=data) + + self.assertEqual(result.status_code, 400) + + def test_entity_not_found(self): + """Test for entity which are not found.""" + result = requests.get( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}'.format("not.existant_entity")), + timeout=5) + + self.assertEqual(result.status_code, 404) + + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format("non.existant_entity")), + timeout=5) + + self.assertEqual(result.status_code, 404) + + def test_allowed_methods(self): + """Test the allowed methods.""" + result = requests.get( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format( + "light.ceiling_lights"))) + + self.assertEqual(result.status_code, 405) + + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}'.format("light.ceiling_lights")), + data={'key1': 'value1'}) + + self.assertEqual(result.status_code, 405) + + result = requests.put( + BRIDGE_URL_BASE.format('/api/username/lights'), + data={'key1': 'value1'}) + + self.assertEqual(result.status_code, 405) + + def test_proper_put_state_request(self): + """Test the request to set the state.""" + # Test proper on value parsing + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format( + 'light.ceiling_lights')), + data=json.dumps({HUE_API_STATE_ON: 1234})) + + self.assertEqual(result.status_code, 400) + + # Test proper brightness value parsing + result = requests.put( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format( + 'light.ceiling_lights')), data=json.dumps({ + HUE_API_STATE_ON: True, + HUE_API_STATE_BRI: 'Hello world!' + })) + + self.assertEqual(result.status_code, 400) + + # pylint: disable=invalid-name + def perform_put_test_on_ceiling_lights(self, + content_type='application/json'): + """Test the setting of a light.""" + # Turn the office light off first + self.hass.services.call( + light.DOMAIN, const.SERVICE_TURN_OFF, + {const.ATTR_ENTITY_ID: 'light.ceiling_lights'}, + blocking=True) + + ceiling_lights = self.hass.states.get('light.ceiling_lights') + self.assertEqual(ceiling_lights.state, STATE_OFF) + + # Go through the API to turn it on + office_result = self.perform_put_light_state( + 'light.ceiling_lights', True, 56, content_type) + + office_result_json = office_result.json() + + self.assertEqual(office_result.status_code, 200) + self.assertTrue( + 'application/json' in office_result.headers['content-type']) + + self.assertEqual(len(office_result_json), 2) + + # Check to make sure the state changed + ceiling_lights = self.hass.states.get('light.ceiling_lights') + self.assertEqual(ceiling_lights.state, STATE_ON) + self.assertEqual(ceiling_lights.attributes[light.ATTR_BRIGHTNESS], 56) + + def perform_get_light_state(self, entity_id, expected_status): + """Test the gettting of a light state.""" + result = requests.get( + BRIDGE_URL_BASE.format( + '/api/username/lights/{}'.format(entity_id)), timeout=5) + + self.assertEqual(result.status_code, expected_status) + + if expected_status == 200: + self.assertTrue( + 'application/json' in result.headers['content-type']) + + return result.json() + + return None + + # pylint: disable=no-self-use + def perform_put_light_state(self, entity_id, is_on, brightness=None, + content_type='application/json'): + """Test the setting of a light state.""" + url = BRIDGE_URL_BASE.format( + '/api/username/lights/{}/state'.format(entity_id)) + + req_headers = {'Content-Type': content_type} + + data = {HUE_API_STATE_ON: is_on} + + if brightness is not None: + data[HUE_API_STATE_BRI] = brightness + + result = requests.put( + url, data=json.dumps(data), timeout=5, headers=req_headers) + + return result diff --git a/tests/components/emulated_hue/test_init.py b/tests/components/emulated_hue/test_init.py new file mode 100755 index 00000000000..ec3cc0a11cb --- /dev/null +++ b/tests/components/emulated_hue/test_init.py @@ -0,0 +1,55 @@ +from unittest.mock import patch + +from homeassistant.components.emulated_hue import Config, _LOGGER + + +def test_config_google_home_entity_id_to_number(): + """Test config adheres to the type.""" + conf = Config({ + 'type': 'google_home' + }) + + number = conf.entity_id_to_number('light.test') + assert number == '1' + + number = conf.entity_id_to_number('light.test') + assert number == '1' + + number = conf.entity_id_to_number('light.test2') + assert number == '2' + + entity_id = conf.number_to_entity_id('1') + assert entity_id == 'light.test' + + +def test_config_alexa_entity_id_to_number(): + """Test config adheres to the type.""" + conf = Config({ + 'type': 'alexa' + }) + + number = conf.entity_id_to_number('light.test') + assert number == 'light.test' + + number = conf.entity_id_to_number('light.test') + assert number == 'light.test' + + number = conf.entity_id_to_number('light.test2') + assert number == 'light.test2' + + entity_id = conf.number_to_entity_id('light.test') + assert entity_id == 'light.test' + + +def test_warning_config_google_home_listen_port(): + """Test we warn when non-default port is used for Google Home.""" + with patch.object(_LOGGER, 'warning') as mock_warn: + Config({ + 'type': 'google_home', + 'host_ip': '123.123.123.123', + 'listen_port': 8300 + }) + + assert mock_warn.called + assert mock_warn.mock_calls[0][1][0] == \ + "When targetting Google Home, listening port has to be port 80" diff --git a/tests/components/emulated_hue/test_upnp.py b/tests/components/emulated_hue/test_upnp.py new file mode 100644 index 00000000000..03b9e993a9b --- /dev/null +++ b/tests/components/emulated_hue/test_upnp.py @@ -0,0 +1,120 @@ +"""The tests for the emulated Hue component.""" +import json + +import unittest +from unittest.mock import patch +import requests + +from homeassistant import bootstrap, const, core +import homeassistant.components as core_components +from homeassistant.components import emulated_hue, http +from homeassistant.util.async import run_coroutine_threadsafe + +from tests.common import get_test_instance_port, get_test_home_assistant + +HTTP_SERVER_PORT = get_test_instance_port() +BRIDGE_SERVER_PORT = get_test_instance_port() + +BRIDGE_URL_BASE = 'http://127.0.0.1:{}'.format(BRIDGE_SERVER_PORT) + '{}' +JSON_HEADERS = {const.HTTP_HEADER_CONTENT_TYPE: const.CONTENT_TYPE_JSON} + + +def setup_hass_instance(emulated_hue_config): + """Set up the Home Assistant instance to test.""" + hass = get_test_home_assistant() + + # We need to do this to get access to homeassistant/turn_(on,off) + run_coroutine_threadsafe( + core_components.async_setup(hass, {core.DOMAIN: {}}), hass.loop + ).result() + + bootstrap.setup_component( + hass, http.DOMAIN, + {http.DOMAIN: {http.CONF_SERVER_PORT: HTTP_SERVER_PORT}}) + + bootstrap.setup_component(hass, emulated_hue.DOMAIN, emulated_hue_config) + + return hass + + +def start_hass_instance(hass): + """Start the Home Assistant instance to test.""" + hass.start() + + +class TestEmulatedHue(unittest.TestCase): + """Test the emulated Hue component.""" + + hass = None + + @classmethod + def setUpClass(cls): + """Setup the class.""" + cls.hass = hass = get_test_home_assistant() + + # We need to do this to get access to homeassistant/turn_(on,off) + run_coroutine_threadsafe( + core_components.async_setup(hass, {core.DOMAIN: {}}), hass.loop + ).result() + + bootstrap.setup_component( + hass, http.DOMAIN, + {http.DOMAIN: {http.CONF_SERVER_PORT: HTTP_SERVER_PORT}}) + + with patch('homeassistant.components' + '.emulated_hue.UPNPResponderThread'): + bootstrap.setup_component(hass, emulated_hue.DOMAIN, { + emulated_hue.DOMAIN: { + emulated_hue.CONF_LISTEN_PORT: BRIDGE_SERVER_PORT + }}) + + cls.hass.start() + + @classmethod + def tearDownClass(cls): + """Stop the class.""" + cls.hass.stop() + + def test_description_xml(self): + """Test the description.""" + import xml.etree.ElementTree as ET + + result = requests.get( + BRIDGE_URL_BASE.format('/description.xml'), timeout=5) + + self.assertEqual(result.status_code, 200) + self.assertTrue('text/xml' in result.headers['content-type']) + + # Make sure the XML is parsable + # pylint: disable=bare-except + try: + ET.fromstring(result.text) + except: + self.fail('description.xml is not valid XML!') + + def test_create_username(self): + """Test the creation of an username.""" + request_json = {'devicetype': 'my_device'} + + result = requests.post( + BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json), + timeout=5) + + self.assertEqual(result.status_code, 200) + self.assertTrue('application/json' in result.headers['content-type']) + + resp_json = result.json() + success_json = resp_json[0] + + self.assertTrue('success' in success_json) + self.assertTrue('username' in success_json['success']) + + def test_valid_username_request(self): + """Test request with a valid username.""" + request_json = {'invalid_key': 'my_device'} + + result = requests.post( + BRIDGE_URL_BASE.format('/api'), data=json.dumps(request_json), + timeout=5) + + self.assertEqual(result.status_code, 400) From cffc7ac4d871fe31f5ee75d0cbbff1f70899476b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 4 Dec 2016 10:59:18 -0800 Subject: [PATCH 022/141] Update netdisco to 0.8 (#4723) --- homeassistant/components/discovery.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py index 142764ea522..3c4dff6eac5 100644 --- a/homeassistant/components/discovery.py +++ b/homeassistant/components/discovery.py @@ -14,7 +14,7 @@ import voluptuous as vol from homeassistant.const import EVENT_HOMEASSISTANT_START from homeassistant.helpers.discovery import load_platform, discover -REQUIREMENTS = ['netdisco==0.7.7'] +REQUIREMENTS = ['netdisco==0.8.0'] DOMAIN = 'discovery' diff --git a/requirements_all.txt b/requirements_all.txt index 3fdf12c086a..622faa3719d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -296,7 +296,7 @@ mficlient==0.3.0 miflora==0.1.13 # homeassistant.components.discovery -netdisco==0.7.7 +netdisco==0.8.0 # homeassistant.components.sensor.neurio_energy neurio==0.2.10 From 87dab37b8a9aad9e63e49c36d1ded3294b4dc10d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 4 Dec 2016 13:49:46 -0800 Subject: [PATCH 023/141] Fix Nest interpreting Celsius temperature as Fahrenheit (#4729) --- homeassistant/components/climate/nest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/climate/nest.py b/homeassistant/components/climate/nest.py index 01c3b3782b1..06ec500f9e2 100644 --- a/homeassistant/components/climate/nest.py +++ b/homeassistant/components/climate/nest.py @@ -229,7 +229,7 @@ class NestThermostat(ClimateDevice): self._eco_temperature = self.device.eco_temperature self._locked_temperature = self.device.locked_temperature self._is_locked = self.device.is_locked - if self.device.temperature == 'C': + if self.device.temperature_scale == 'C': self._temperature_scale = TEMP_CELSIUS else: self._temperature_scale = TEMP_FAHRENHEIT From 64b1179c1309b8d0b93fd80a29a7f508bcbbc082 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Sun, 4 Dec 2016 17:33:50 -0500 Subject: [PATCH 024/141] Make sure all nest platforms require discovery info (#4734) --- homeassistant/components/binary_sensor/nest.py | 3 +++ homeassistant/components/camera/nest.py | 1 + homeassistant/components/climate/nest.py | 3 ++- homeassistant/components/sensor/nest.py | 3 +++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/binary_sensor/nest.py b/homeassistant/components/binary_sensor/nest.py index d78e33c9f95..070703df32a 100644 --- a/homeassistant/components/binary_sensor/nest.py +++ b/homeassistant/components/binary_sensor/nest.py @@ -60,6 +60,9 @@ _LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup Nest binary sensors.""" + if discovery_info is None: + return + nest = hass.data[DATA_NEST] conf = config.get(CONF_MONITORED_CONDITIONS, _VALID_BINARY_SENSOR_TYPES) diff --git a/homeassistant/components/camera/nest.py b/homeassistant/components/camera/nest.py index 8bda0e8eb9c..aa2041e07a6 100644 --- a/homeassistant/components/camera/nest.py +++ b/homeassistant/components/camera/nest.py @@ -26,6 +26,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up a Nest Cam.""" if discovery_info is None: return + camera_devices = hass.data[nest.DATA_NEST].camera_devices() cameras = [NestCamera(structure, device) for structure, device in camera_devices] diff --git a/homeassistant/components/climate/nest.py b/homeassistant/components/climate/nest.py index 06ec500f9e2..dbc68162579 100644 --- a/homeassistant/components/climate/nest.py +++ b/homeassistant/components/climate/nest.py @@ -31,10 +31,11 @@ STATE_HEAT_COOL = 'heat-cool' def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Nest thermostat.""" - _LOGGER.debug("Setting up nest thermostat") if discovery_info is None: return + _LOGGER.debug("Setting up nest thermostat") + temp_unit = hass.config.units.temperature_unit add_devices( diff --git a/homeassistant/components/sensor/nest.py b/homeassistant/components/sensor/nest.py index b4909aebae3..53f767ab494 100644 --- a/homeassistant/components/sensor/nest.py +++ b/homeassistant/components/sensor/nest.py @@ -68,6 +68,9 @@ _LOGGER = logging.getLogger(__name__) def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Nest Sensor.""" + if discovery_info is None: + return + nest = hass.data[DATA_NEST] conf = config.get(CONF_MONITORED_CONDITIONS, _VALID_SENSOR_TYPES) From 2099d023ef0b86195adeaa41d3d80e02dfdfa2ec Mon Sep 17 00:00:00 2001 From: Lukas Date: Mon, 5 Dec 2016 00:08:14 +0100 Subject: [PATCH 025/141] [0.34] bugfix influxdb node_id (#4712) * Bugfix for #4709 - do not convert node_id to float * Update influxdb.py --- homeassistant/components/influxdb.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/influxdb.py b/homeassistant/components/influxdb.py index 167767bc00e..08296ad65c7 100644 --- a/homeassistant/components/influxdb.py +++ b/homeassistant/components/influxdb.py @@ -120,7 +120,8 @@ def setup(hass, config): for key, value in state.attributes.items(): if key != 'unit_of_measurement': - if isinstance(value, (str, float, bool)): + if isinstance(value, (str, float, bool)) or \ + key.endswith('_id'): json_body[0]['fields'][key] = value elif isinstance(value, int): # Prevent column data errors in influxDB. From 2b3caa716a66075543856382056fafa72d3718df Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 4 Dec 2016 15:30:55 -0800 Subject: [PATCH 026/141] Cast progress (#4735) * add progress to google cast * Add progress to media player demo --- homeassistant/components/media_player/cast.py | 27 ++++++++ homeassistant/components/media_player/demo.py | 68 ++++++++++++++----- 2 files changed, 78 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index 1d01f0058ec..0f3b98cab46 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -18,6 +18,7 @@ from homeassistant.const import ( CONF_HOST, STATE_IDLE, STATE_OFF, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN) import homeassistant.helpers.config_validation as cv +import homeassistant.util.dt as dt_util REQUIREMENTS = ['pychromecast==0.7.6'] @@ -105,6 +106,7 @@ class CastDevice(MediaPlayerDevice): self.cast_status = self.cast.status self.media_status = self.cast.media_controller.status + self.media_status_received = None @property def should_poll(self): @@ -231,6 +233,30 @@ class CastDevice(MediaPlayerDevice): """Flag of media commands that are supported.""" return SUPPORT_CAST + @property + def media_position(self): + """Position of current playing media in seconds.""" + if self.media_status is None or not ( + self.media_status.player_is_playing or + self.media_status.player_is_idle): + return None + + position = self.media_status.current_time + + if self.media_status.player_is_playing: + position += (dt_util.utcnow() - + self.media_status_received).total_seconds() + + return position + + @property + def media_position_updated_at(self): + """When was the position of the current playing media valid. + + Returns value from homeassistant.util.dt.utcnow(). + """ + return self.media_status_received + def turn_on(self): """Turn on the ChromeCast.""" # The only way we can turn the Chromecast is on is by launching an app @@ -292,4 +318,5 @@ class CastDevice(MediaPlayerDevice): def new_media_status(self, status): """Called when a new media status is received.""" self.media_status = status + self.media_status_received = dt_util.utcnow() self.schedule_update_ha_state() diff --git a/homeassistant/components/media_player/demo.py b/homeassistant/components/media_player/demo.py index 1c1687de319..226ddfe4769 100644 --- a/homeassistant/components/media_player/demo.py +++ b/homeassistant/components/media_player/demo.py @@ -10,6 +10,7 @@ from homeassistant.components.media_player import ( SUPPORT_TURN_OFF, SUPPORT_TURN_ON, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_SELECT_SOURCE, SUPPORT_CLEAR_PLAYLIST, MediaPlayerDevice) from homeassistant.const import STATE_OFF, STATE_PAUSED, STATE_PLAYING +import homeassistant.util.dt as dt_util # pylint: disable=unused-argument @@ -18,8 +19,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None): add_devices([ DemoYoutubePlayer( 'Living Room', 'eyU3bRy2x44', - '♥♥ The Best Fireplace Video (3 hours)'), - DemoYoutubePlayer('Bedroom', 'kxopViU98Xo', 'Epic sax guy 10 hours'), + '♥♥ The Best Fireplace Video (3 hours)', 300), + DemoYoutubePlayer('Bedroom', 'kxopViU98Xo', 'Epic sax guy 10 hours', + 360000), DemoMusicPlayer(), DemoTVShowPlayer(), ]) @@ -78,32 +80,32 @@ class AbstractDemoPlayer(MediaPlayerDevice): def turn_on(self): """Turn the media player on.""" self._player_state = STATE_PLAYING - self.update_ha_state() + self.schedule_update_ha_state() def turn_off(self): """Turn the media player off.""" self._player_state = STATE_OFF - self.update_ha_state() + self.schedule_update_ha_state() def mute_volume(self, mute): """Mute the volume.""" self._volume_muted = mute - self.update_ha_state() + self.schedule_update_ha_state() def set_volume_level(self, volume): """Set the volume level, range 0..1.""" self._volume_level = volume - self.update_ha_state() + self.schedule_update_ha_state() def media_play(self): """Send play command.""" self._player_state = STATE_PLAYING - self.update_ha_state() + self.schedule_update_ha_state() def media_pause(self): """Send pause command.""" self._player_state = STATE_PAUSED - self.update_ha_state() + self.schedule_update_ha_state() class DemoYoutubePlayer(AbstractDemoPlayer): @@ -111,11 +113,14 @@ class DemoYoutubePlayer(AbstractDemoPlayer): # We only implement the methods that we support - def __init__(self, name, youtube_id=None, media_title=None): + def __init__(self, name, youtube_id=None, media_title=None, duration=360): """Initialize the demo device.""" super().__init__(name) self.youtube_id = youtube_id self._media_title = media_title + self._duration = duration + self._progress = int(duration * .15) + self._progress_updated_at = dt_util.utcnow() @property def media_content_id(self): @@ -130,7 +135,7 @@ class DemoYoutubePlayer(AbstractDemoPlayer): @property def media_duration(self): """Return the duration of current playing media in seconds.""" - return 360 + return self._duration @property def media_image_url(self): @@ -152,10 +157,39 @@ class DemoYoutubePlayer(AbstractDemoPlayer): """Flag of media commands that are supported.""" return YOUTUBE_PLAYER_SUPPORT + @property + def media_position(self): + """Position of current playing media in seconds.""" + if self._progress is None: + return None + + position = self._progress + + if self._player_state == STATE_PLAYING: + position += (dt_util.utcnow() - + self._progress_updated_at).total_seconds() + + return position + + @property + def media_position_updated_at(self): + """When was the position of the current playing media valid. + + Returns value from homeassistant.util.dt.utcnow(). + """ + if self._player_state == STATE_PLAYING: + return self._progress_updated_at + def play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" self.youtube_id = media_id - self.update_ha_state() + self.schedule_update_ha_state() + + def media_pause(self): + """Send pause command.""" + self._progress = self.media_position + self._progress_updated_at = dt_util.utcnow() + super().media_pause() class DemoMusicPlayer(AbstractDemoPlayer): @@ -249,20 +283,20 @@ class DemoMusicPlayer(AbstractDemoPlayer): """Send previous track command.""" if self._cur_track > 0: self._cur_track -= 1 - self.update_ha_state() + self.schedule_update_ha_state() def media_next_track(self): """Send next track command.""" if self._cur_track < len(self.tracks) - 1: self._cur_track += 1 - self.update_ha_state() + self.schedule_update_ha_state() def clear_playlist(self): """Clear players playlist.""" self.tracks = [] self._cur_track = 0 self._player_state = STATE_OFF - self.update_ha_state() + self.schedule_update_ha_state() class DemoTVShowPlayer(AbstractDemoPlayer): @@ -344,15 +378,15 @@ class DemoTVShowPlayer(AbstractDemoPlayer): """Send previous track command.""" if self._cur_episode > 1: self._cur_episode -= 1 - self.update_ha_state() + self.schedule_update_ha_state() def media_next_track(self): """Send next track command.""" if self._cur_episode < self._episode_count: self._cur_episode += 1 - self.update_ha_state() + self.schedule_update_ha_state() def select_source(self, source): """Set the input source.""" self._source = source - self.update_ha_state() + self.schedule_update_ha_state() From 5a7e44664694d940db4c98b456a6c89b5cc7f694 Mon Sep 17 00:00:00 2001 From: Daniel Hoyer Iversen Date: Sat, 3 Dec 2016 23:44:06 +0100 Subject: [PATCH 027/141] device tracker --- homeassistant/components/device_tracker/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index 91f0720e927..eaa0621b04c 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -332,7 +332,6 @@ class Device(Entity): gps = None # type: GPSType gps_accuracy = 0 last_seen = None # type: dt_util.dt.datetime - battery = None # type: str attributes = None # type: dict vendor = None # type: str @@ -396,9 +395,6 @@ class Device(Entity): attr[ATTR_LONGITUDE] = self.gps[1] attr[ATTR_GPS_ACCURACY] = self.gps_accuracy - if self.battery: - attr[ATTR_BATTERY] = self.battery - if self.attributes: for key, value in self.attributes.items(): attr[key] = value @@ -419,8 +415,13 @@ class Device(Entity): self.host_name = host_name self.location_name = location_name self.gps_accuracy = gps_accuracy or 0 - self.battery = battery - self.attributes = attributes + if (battery or attributes) and self.attributes is None: + self.attributes = {} + if battery: + self.attributes[ATTR_BATTERY] = battery + if attributes: + for key, value in attributes.items(): + self.attributes[key] = value self.gps = None if gps is not None: From 03d19ec2f1b58001fdf829d080f0e0e981c4ebd3 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 5 Dec 2016 11:19:20 +0100 Subject: [PATCH 028/141] Netdata sensor (#4743) * Added netdata sensor * Typo * Add netdata sensor * Improvement of the work done by @ezar --- .coveragerc | 1 + homeassistant/components/sensor/netdata.py | 147 +++++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 homeassistant/components/sensor/netdata.py diff --git a/.coveragerc b/.coveragerc index 9078b199a3e..6d5abe745f8 100644 --- a/.coveragerc +++ b/.coveragerc @@ -281,6 +281,7 @@ omit = homeassistant/components/sensor/mhz19.py homeassistant/components/sensor/miflora.py homeassistant/components/sensor/mqtt_room.py + homeassistant/components/sensor/netdata.py homeassistant/components/sensor/neurio_energy.py homeassistant/components/sensor/nut.py homeassistant/components/sensor/nzbget.py diff --git a/homeassistant/components/sensor/netdata.py b/homeassistant/components/sensor/netdata.py new file mode 100644 index 00000000000..3a87eeb5ceb --- /dev/null +++ b/homeassistant/components/sensor/netdata.py @@ -0,0 +1,147 @@ +""" +Support gathering system information of hosts which are running netdata. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.netdata/ +""" +import logging +from datetime import timedelta + +import requests +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ( + CONF_HOST, CONF_PORT, STATE_UNKNOWN, CONF_NAME, CONF_RESOURCES) +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle + +_LOGGER = logging.getLogger(__name__) +_RESOURCE = 'api/v1' +_REALTIME = 'before=0&after=-1&options=seconds' + +DEFAULT_HOST = 'localhost' +DEFAULT_NAME = 'Netdata' +DEFAULT_PORT = '19999' + +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) + +SENSOR_TYPES = { + 'memory_free': ['RAM Free', 'MiB', 'system.ram', 'free', 1], + 'memory_used': ['RAM Used', 'MiB', 'system.ram', 'used', 1], + 'memory_cached': ['RAM Cached', 'MiB', 'system.ram', 'cached', 1], + 'memory_buffers': ['RAM Buffers', 'MiB', 'system.ram', 'buffers', 1], + 'swap_free': ['Swap Free', 'MiB', 'system.swap', 'free', 1], + 'swap_used': ['Swap Used', 'MiB', 'system.swap', 'used', 1], + 'processes_running': ['Processes Running', 'Count', 'system.processes', + 'running', 0], + 'processes_blocked': ['Processes Blocked', 'Count', 'system.processes', + 'blocked', 0], + 'system_load': ['System Load', '15 min', 'system.processes', 'running', 2], + 'system_io_in': ['System IO In', 'Count', 'system.io', 'in', 0], + 'system_io_out': ['System IO Out', 'Count', 'system.io', 'out', 0], +} + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_RESOURCES, default=['memory_free']): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), +}) + + +# pylint: disable=unused-variable +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the Netdata sensor.""" + name = config.get(CONF_NAME) + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + url = 'http://{}:{}'.format(host, port) + version_url = '{}/version.txt'.format(url) + data_url = '{}/{}/data?chart='.format(url, _RESOURCE) + resources = config.get(CONF_RESOURCES) + + try: + response = requests.get(version_url, timeout=10) + if not response.ok: + _LOGGER.error("Response status is '%s'", response.status_code) + return False + except requests.exceptions.ConnectionError: + _LOGGER.error("No route to resource/endpoint: %s", url) + return False + + values = {} + for key, value in sorted(SENSOR_TYPES.items()): + if key in resources: + values.setdefault(value[2], []).append(key) + + dev = [] + for chart in values: + rest_url = '{}{}&{}'.format(data_url, chart, _REALTIME) + rest = NetdataData(rest_url) + for sensor_type in values[chart]: + dev.append(NetdataSensor(rest, name, sensor_type)) + + add_devices(dev) + + +class NetdataSensor(Entity): + """Implementation of a Netdata sensor.""" + + def __init__(self, rest, name, sensor_type): + """Initialize the sensor.""" + self.rest = rest + self.type = sensor_type + self._name = '{} {}'.format(name, SENSOR_TYPES[self.type][0]) + self._precision = SENSOR_TYPES[self.type][4] + self._unit_of_measurement = SENSOR_TYPES[self.type][1] + self.update() + + @property + def name(self): + """The name of the sensor.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit the value is expressed in.""" + return self._unit_of_measurement + + @property + def state(self): + """Return the state of the resources.""" + value = self.rest.data + + if value is not None: + netdata_id = SENSOR_TYPES[self.type][3] + if netdata_id in value: + return "{0:.{1}f}".format(value[netdata_id], self._precision) + else: + return STATE_UNKNOWN + + def update(self): + """Get the latest data from Netdata REST API.""" + self.rest.update() + + +class NetdataData(object): + """The class for handling the data retrieval.""" + + def __init__(self, resource): + """Initialize the data object.""" + self._resource = resource + self.data = None + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Get the latest data from the Netdata REST API.""" + try: + response = requests.get(self._resource, timeout=5) + det = response.json() + self.data = {k: v for k, v in zip(det['labels'], det['data'][0])} + + except requests.exceptions.ConnectionError: + _LOGGER.error("No route to host/endpoint: %s", self._resource) + self.data = None From e21382cd3e810e152f5f3191fa4fd407d84b3213 Mon Sep 17 00:00:00 2001 From: rubund Date: Mon, 5 Dec 2016 17:15:36 +0100 Subject: [PATCH 029/141] Fix broken EnOcean support (#4710) * ensure_list * CONF_ID is not required configuration for enocean lights * Use vol.All(cv.ensure_list, [vol.Coerce(int)]) as suggested in pull request review * Fix line too long --- homeassistant/components/binary_sensor/enocean.py | 2 +- homeassistant/components/light/enocean.py | 5 +++-- homeassistant/components/sensor/enocean.py | 2 +- homeassistant/components/switch/enocean.py | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/binary_sensor/enocean.py b/homeassistant/components/binary_sensor/enocean.py index 631ed0021e1..bd68a232f22 100644 --- a/homeassistant/components/binary_sensor/enocean.py +++ b/homeassistant/components/binary_sensor/enocean.py @@ -20,7 +20,7 @@ DEPENDENCIES = ['enocean'] DEFAULT_NAME = 'EnOcean binary sensor' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_ID): cv.string, + vol.Required(CONF_ID): vol.All(cv.ensure_list, [vol.Coerce(int)]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA, }) diff --git a/homeassistant/components/light/enocean.py b/homeassistant/components/light/enocean.py index ce65d8cc041..e24aca4902d 100644 --- a/homeassistant/components/light/enocean.py +++ b/homeassistant/components/light/enocean.py @@ -26,8 +26,9 @@ DEPENDENCIES = ['enocean'] SUPPORT_ENOCEAN = SUPPORT_BRIGHTNESS PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_ID): cv.string, - vol.Required(CONF_SENDER_ID): cv.string, + vol.Optional(CONF_ID, default=[]): vol.All(cv.ensure_list, + [vol.Coerce(int)]), + vol.Required(CONF_SENDER_ID): vol.All(cv.ensure_list, [vol.Coerce(int)]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) diff --git a/homeassistant/components/sensor/enocean.py b/homeassistant/components/sensor/enocean.py index e998b5c9c46..009718dd720 100644 --- a/homeassistant/components/sensor/enocean.py +++ b/homeassistant/components/sensor/enocean.py @@ -20,7 +20,7 @@ DEFAULT_NAME = 'EnOcean sensor' DEPENDENCIES = ['enocean'] PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_ID): cv.string, + vol.Required(CONF_ID): vol.All(cv.ensure_list, [vol.Coerce(int)]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) diff --git a/homeassistant/components/switch/enocean.py b/homeassistant/components/switch/enocean.py index 71bd180ad10..ead5d789bbd 100644 --- a/homeassistant/components/switch/enocean.py +++ b/homeassistant/components/switch/enocean.py @@ -20,7 +20,7 @@ DEFAULT_NAME = 'EnOcean Switch' DEPENDENCIES = ['enocean'] PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_ID): cv.string, + vol.Required(CONF_ID): vol.All(cv.ensure_list, [vol.Coerce(int)]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) From 13006cee685111e7de106f369f6ae8b09c250439 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 5 Dec 2016 11:32:17 -0800 Subject: [PATCH 030/141] Device tracker attributes (#4753) --- .../components/device_tracker/__init__.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index e95b556b998..7c4c74708db 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -332,6 +332,7 @@ class Device(Entity): gps = None # type: GPSType gps_accuracy = 0 last_seen = None # type: dt_util.dt.datetime + battery = None # type: str attributes = None # type: dict vendor = None # type: str @@ -369,6 +370,7 @@ class Device(Entity): self.away_hide = hide_if_away self.vendor = vendor + self._attributes = {} @property def name(self): @@ -395,12 +397,16 @@ class Device(Entity): attr[ATTR_LONGITUDE] = self.gps[1] attr[ATTR_GPS_ACCURACY] = self.gps_accuracy - if self.attributes: - for key, value in self.attributes.items(): - attr[key] = value + if self.battery: + attr[ATTR_BATTERY] = self.battery return attr + @property + def device_state_attributes(self): + """Return device state attributes.""" + return self._attributes + @property def hidden(self): """If device should be hidden.""" @@ -415,13 +421,10 @@ class Device(Entity): self.host_name = host_name self.location_name = location_name self.gps_accuracy = gps_accuracy or 0 - if (battery or attributes) and self.attributes is None: - self.attributes = {} - if battery: - self.attributes[ATTR_BATTERY] = battery + if attributes: - for key, value in attributes.items(): - self.attributes[key] = value + self._attributes.update(attributes) + self.gps = None if gps is not None: From 308744d8a022c7fc25af4f2ef8a6214cdcf014f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Mon, 5 Dec 2016 20:33:51 +0100 Subject: [PATCH 031/141] Add additional attributes to GPSLogger (#4755) --- homeassistant/components/device_tracker/gpslogger.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/gpslogger.py b/homeassistant/components/device_tracker/gpslogger.py index 2e897ccb10c..d8e7ca8b074 100644 --- a/homeassistant/components/device_tracker/gpslogger.py +++ b/homeassistant/components/device_tracker/gpslogger.py @@ -63,10 +63,20 @@ class GPSLoggerView(HomeAssistantView): accuracy = int(float(data['accuracy'])) if 'battery' in data: battery = float(data['battery']) + attrs = {} + if 'speed' in data: + attrs['speed'] = float(data['speed']) + if 'direction' in data: + attrs['direction'] = float(data['direction']) + if 'altitude' in data: + attrs['altitude'] = float(data['altitude']) + if 'provider' in data: + attrs['provider'] = data['provider'] yield from hass.loop.run_in_executor( None, partial(self.see, dev_id=device, gps=gps_location, battery=battery, - gps_accuracy=accuracy)) + gps_accuracy=accuracy, + attributes=attrs)) return 'Setting location for {}'.format(device) From b3253403aae44d47cd624050ee5f39e5a56ccec5 Mon Sep 17 00:00:00 2001 From: Jeff Wilson Date: Mon, 5 Dec 2016 20:39:40 -0500 Subject: [PATCH 032/141] Set hue-bridgeid in UPNP response (#4740) --- homeassistant/components/emulated_hue/upnp.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/emulated_hue/upnp.py b/homeassistant/components/emulated_hue/upnp.py index f81a8c1b68d..fd880c40e6e 100644 --- a/homeassistant/components/emulated_hue/upnp.py +++ b/homeassistant/components/emulated_hue/upnp.py @@ -74,6 +74,7 @@ CACHE-CONTROL: max-age=60 EXT: LOCATION: http://{0}:{1}/description.xml SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/0.1 +hue-bridgeid: 1234 ST: urn:schemas-upnp-org:device:basic:1 USN: uuid:Socket-1_0-221438K0100073::urn:schemas-upnp-org:device:basic:1 From 1ae8256ffd63983738adf7ed7d947e4d689d889d Mon Sep 17 00:00:00 2001 From: "Martin J. Laubach" Date: Tue, 6 Dec 2016 02:50:50 +0100 Subject: [PATCH 033/141] Add sensor for reading Austrian ZAMG weather conditions (#4347) * Add sensor for reading ZAMG weather conditions * Add to coveragerc; Correct some doc style problems * More doc fixes * More doc fixes * Lose license and whatever. * Don't return UNKNOWN for unknown variables * Verify that the configured station id is actually one in the data set. Don't warn about unknown stations, this cannot happen any more as the configuration parser now checks that. This could still happen if the data set is incomplete though ... * Clean up imports * Clarify comment on throttling interval * Base zamg sensor on Entity, not WeatherEntity, and delete unused code * Fix formatting nits from flake8 * Use ATTR_FRIENDLY_NAME, clean up imports, remove unnecessary indirection. * Use {}.format() instead of "" % * Re-add unit of measurement that got lost somehow * Use guard clauses instead of if-matroshka. Wrap requests.get() in try/except for RequestException. * Huh, how did this happen? White space corrections... * Add sensor for reading ZAMG weather conditions * Add to coveragerc; Correct some doc style problems * More doc fixes * More doc fixes * Verify that the configured station id is actually one in the data set. Don't warn about unknown stations, this cannot happen any more as the configuration parser now checks that. This could still happen if the data set is incomplete though ... * Lose license and whatever. * Don't return UNKNOWN for unknown variables * Clean up imports * Clarify comment on throttling interval * Base zamg sensor on Entity, not WeatherEntity, and delete unused code * Fix formatting nits from flake8 * Use ATTR_FRIENDLY_NAME, clean up imports, remove unnecessary indirection. * Use {}.format() instead of "" % * Re-add unit of measurement that got lost somehow * Use guard clauses instead of if-matroshka. Wrap requests.get() in try/except for RequestException. * Huh, how did this happen? White space corrections... * Precipitation actually is a float, good it rained today * Logger needs no module visibility * Do not name sensors with _ to be in line with the other weather sensor platforms. * Remove manually set friendly_name * comment format police * Less comments * Update zamg.py --- .coveragerc | 2 +- homeassistant/components/sensor/zamg.py | 247 ++++++++++++++++++++++++ 2 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/sensor/zamg.py diff --git a/.coveragerc b/.coveragerc index 6d5abe745f8..5dcc37e1402 100644 --- a/.coveragerc +++ b/.coveragerc @@ -315,7 +315,7 @@ omit = homeassistant/components/sensor/waqi.py homeassistant/components/sensor/xbox_live.py homeassistant/components/sensor/yweather.py - homeassistant/components/sensor/waqi.py + homeassistant/components/sensor/zamg.py homeassistant/components/switch/acer_projector.py homeassistant/components/switch/anel_pwrctrl.py homeassistant/components/switch/arest.py diff --git a/homeassistant/components/sensor/zamg.py b/homeassistant/components/sensor/zamg.py new file mode 100644 index 00000000000..d3d64690ef6 --- /dev/null +++ b/homeassistant/components/sensor/zamg.py @@ -0,0 +1,247 @@ +""" +Sensor for data from Austrian "Zentralanstalt für Meteorologie und Geodynamik". + +This is a sensor for the Austrian weather service "Zentralanstalt für +Meteorologie und Geodynamik" (aka ZAMG). + +The configuration should look like this: + + - platform: zamg + station_id: 11035 + monitored_conditions: + - temperature + - humidity + - pressure + - wind_speed + - precipitation + +Recognised conditions are: + + pressure (Pressure at station level) + pressure_sealevel (Pressure at Sea Level) + humidity (Humidity) + wind_speed (Wind Speed) + wind_bearing (Wind Bearing) + wind_max_speed (Top Wind Speed) + wind_max_bearing (Top Wind Bearing) + sun_last_hour (Sun Last Hour Percentage) + temperature (Temperature) + precipitation (Precipitation) + dewpoint (Dew Point) + +The following stations are available in the data set: + + 11010 Linz/Hörsching + 11012 Kremsmünster + 11022 Retz + 11035 Wien/Hohe Warte + 11036 Wien/Schwechat + 11101 Bregenz + 11121 Innsbruck + 11126 Patscherkofel + 11130 Kufstein + 11150 Salzburg + 11155 Feuerkogel + 11157 Aigen im Ennstal + 11171 Mariazell + 11190 Eisenstadt + 11204 Lienz +""" + +import csv +from datetime import timedelta +import logging +import requests + +import voluptuous as vol + +from homeassistant.components.weather import ( + ATTR_WEATHER_HUMIDITY, ATTR_WEATHER_ATTRIBUTION, + ATTR_WEATHER_PRESSURE, ATTR_WEATHER_TEMPERATURE, + ATTR_WEATHER_WIND_BEARING, ATTR_WEATHER_WIND_SPEED, +) +import homeassistant.helpers.config_validation as cv +from homeassistant.const import ( + CONF_MONITORED_CONDITIONS, CONF_NAME, __version__ +) +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle + +DEFAULT_NAME = 'zamg' +ATTRIBUTION = 'Data provided by ZAMG' + +# Data source only updates once per hour, so throttle to 30min to have +# reasonably recent data +MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30) + +CONF_STATION_ID = "station_id" + +VALID_STATION_IDS = ( + '11010', '11012', '11022', '11035', '11036', '11101', '11121', '11126', + '11130', '11150', '11155', '11157', '11171', '11190', '11204' +) + +SENSOR_TYPES = { + ATTR_WEATHER_PRESSURE: ('Pressure', 'hPa', 'LDstat hPa', float), + 'pressure_sealevel': ('Pressure at Sea Level', 'hPa', 'LDred hPa', float), + ATTR_WEATHER_HUMIDITY: ('Humidity', '%', 'RF %', int), + ATTR_WEATHER_WIND_SPEED: ('Wind Speed', 'km/h', 'WG km/h', float), + ATTR_WEATHER_WIND_BEARING: ('Wind Bearing', '°', 'WR °', int), + 'wind_max_speed': ('Top Wind Speed', 'km/h', 'WSG km/h', float), + 'wind_max_bearing': ('Top Wind Bearing', '°', 'WSR °', int), + 'sun_last_hour': ('Sun Last Hour', '%', 'SO %', int), + ATTR_WEATHER_TEMPERATURE: ('Temperature', '°C', 'T °C', float), + 'precipitation': ('Precipitation', 'l/m²', 'N l/m²', float), + 'dewpoint': ('Dew Point', '°C', 'TP °C', float), + # The following probably not useful for general consumption, + # but we need them to fill in internal attributes + 'station_name': ('Station Name', None, 'Name', str), + 'station_elevation': ('Station Elevation', 'm', 'Höhe m', int), + 'update_date': ('Update Date', None, 'Datum', str), + 'update_time': ('Update Time', None, 'Zeit', str), +} + +PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Required(CONF_STATION_ID): + vol.All(cv.string, vol.In(VALID_STATION_IDS)), + vol.Required(CONF_MONITORED_CONDITIONS): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup platform.""" + station_id = config.get(CONF_STATION_ID) + name = config.get(CONF_NAME) + + logger = logging.getLogger(__name__) + probe = ZamgData(station_id=station_id, logger=logger) + + sensors = [ZAMGWeather(probe, variable, name) + for variable in config[CONF_MONITORED_CONDITIONS]] + + add_devices(sensors, True) + + +class ZAMGWeather(Entity): + """ + I am a weather wrapper for a specific station and a specific attribute. + + Multiple instances (one for each condition) will refer to the same + probe, so things will only get fetched once. + """ + + def __init__(self, probe, variable, name): + """Init condition sensor.""" + self.probe = probe + self.client_name = name + self.variable = variable + + def update(self): + """Delegate update to probe.""" + self.probe.update() + + @property + def name(self): + """Build name of sensor.""" + return '{} {}'.format(self.client_name, self.variable) + + @property + def state(self): + """Return state.""" + return self.probe.get_data(self.variable) + + @property + def unit_of_measurement(self): + """Unit of measurement.""" + return SENSOR_TYPES[self.variable][1] + + @property + def state_attributes(self): + """Return the state attributes.""" + return { + ATTR_WEATHER_ATTRIBUTION: ATTRIBUTION, + "station": self.probe.get_data('station_name'), + "updated": "%s %s" % (self.probe.get_data('update_date'), + self.probe.get_data('update_time')) + } + + +class ZamgData(object): + """ + I represent weather data for a specific site. + + From the web site: + + Sie beinhalten neben Stationsnummer, Stationsname, Seehöhe der Station, + Messdatum und Messzeit (Lokalzeit) die meteorologischen Messwerte von + Temperatur, Taupunkt, relative Luftfeuchtigkeit, Richtung und + Geschwindigkeit des Windmittels und der Windspitze, Niederschlagssumme + der letzten Stunde, Luftdruck reduziert auf Meeresniveau und Luftdruck + auf Stationsniveau sowie die Sonnenscheindauer der letzten Stunde (in + Prozent). Die Messstationen, die diese Daten liefern, sind über das + Bundesgebiet verteilt und beinhalten alle Landeshauptstädte sowie + die wichtigsten Bergstationen. + """ + + API_URL = "http://www.zamg.ac.at/ogd/" + + API_FIELDS = { + v[2]: (k, v[3]) + for k, v in SENSOR_TYPES.items() + } + + API_HEADERS = { + 'User-Agent': 'home-assistant.zamg/' + __version__, + } + + def __init__(self, logger, station_id): + """Initialize the probe.""" + self._logger = logger + self._station_id = station_id + self.data = {} + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """ + Update data set. + + Fetch a new data set from the zamg server, parse it and + update internal state accordingly + """ + try: + response = requests.get(self.API_URL, + headers=self.API_HEADERS, timeout=15) + except requests.exceptions.RequestException: + self._logger.exception("While fetching data from server") + return + + if response.status_code != 200: + self._logger.error("API call returned with status %s", + response.status_code) + return + + content_type = response.headers.get('Content-Type', 'whatever') + if content_type != 'text/csv': + self._logger.error("Expected text/csv but got %s", + content_type) + return + + response.encoding = 'UTF8' + content = response.text + data = (line for line in content.split('\n')) + reader = csv.DictReader(data, delimiter=';', quotechar='"') + for row in reader: + if row.get("Station", None) == self._station_id: + self.data = { + self.API_FIELDS.get(k)[0]: + self.API_FIELDS.get(k)[1](v.replace(',', '.')) + for k, v in row.items() + if v and k in self.API_FIELDS + } + break + + def get_data(self, variable): + """Generic accessor for data.""" + return self.data.get(variable) From fa8bc0a36ccefdf64b78ab63be9ccd7d4c0f890e Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Tue, 6 Dec 2016 02:51:58 +0100 Subject: [PATCH 034/141] Add Verisure smartcam capture service (#4559) * Add verisure capture as service * docstyle --- homeassistant/components/services.yaml | 9 +++++++++ homeassistant/components/verisure.py | 27 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/homeassistant/components/services.yaml b/homeassistant/components/services.yaml index 46a3a46ced6..54c0e18a3ee 100644 --- a/homeassistant/components/services.yaml +++ b/homeassistant/components/services.yaml @@ -144,3 +144,12 @@ openalpr: restart: description: Restart ffmpeg process of device. + +verisure: + capture_smartcam: + description: Capture a new image from a smartcam. + + fields: + device_serial: + description: The serial number of the smartcam you want to capture an image from. + example: '2DEU AT5Z' diff --git a/homeassistant/components/verisure.py b/homeassistant/components/verisure.py index c8241d8fae5..f2b091aa0f1 100644 --- a/homeassistant/components/verisure.py +++ b/homeassistant/components/verisure.py @@ -7,6 +7,7 @@ https://home-assistant.io/components/verisure/ import logging import threading import time +import os.path from datetime import timedelta import voluptuous as vol @@ -14,12 +15,14 @@ import voluptuous as vol from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.helpers import discovery from homeassistant.util import Throttle +import homeassistant.config as conf_util import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['vsure==0.11.1'] _LOGGER = logging.getLogger(__name__) +ATTR_DEVICE_SERIAL = 'device_serial' CONF_ALARM = 'alarm' CONF_CODE_DIGITS = 'code_digits' CONF_HYDROMETERS = 'hygrometers' @@ -29,6 +32,7 @@ CONF_SMARTPLUGS = 'smartplugs' CONF_THERMOMETERS = 'thermometers' CONF_SMARTCAM = 'smartcam' DOMAIN = 'verisure' +SERVICE_CAPTURE_SMARTCAM = 'capture_smartcam' HUB = None @@ -47,6 +51,10 @@ CONFIG_SCHEMA = vol.Schema({ }), }, extra=vol.ALLOW_EXTRA) +CAPTURE_IMAGE_SCHEMA = vol.Schema({ + vol.Required(ATTR_DEVICE_SERIAL): cv.string +}) + def setup(hass, config): """Setup the Verisure component.""" @@ -60,6 +68,20 @@ def setup(hass, config): 'camera'): discovery.load_platform(hass, component, DOMAIN, {}, config) + descriptions = conf_util.load_yaml_config_file( + os.path.join(os.path.dirname(__file__), 'services.yaml')) + + def capture_smartcam(service): + """Capture a new picture from a smartcam.""" + device_id = service.data.get(ATTR_DEVICE_SERIAL) + HUB.smartcam_capture(device_id) + _LOGGER.debug('Capturing new image from %s', ATTR_DEVICE_SERIAL) + + hass.services.register(DOMAIN, SERVICE_CAPTURE_SMARTCAM, + capture_smartcam, + descriptions[DOMAIN][SERVICE_CAPTURE_SMARTCAM], + schema=CAPTURE_IMAGE_SCHEMA) + return True @@ -150,6 +172,11 @@ class VerisureHub(object): self.smartcam_dict = self.my_pages.smartcam.get_imagelist() _LOGGER.debug('New dict: %s', self.smartcam_dict) + @Throttle(timedelta(seconds=30)) + def smartcam_capture(self, device_id): + """Capture a new image from a smartcam.""" + self.my_pages.smartcam.capture(device_id) + @property def available(self): """Return True if hub is available.""" From b60f5714fc088d672322d3c4b6565558cc254c9b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 5 Dec 2016 18:03:06 -0800 Subject: [PATCH 035/141] Fix websocket async (#4752) * Ensure we write to websocket from inside event loop * Inline service call helper --- homeassistant/components/websocket_api.py | 70 ++++++++++++----------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/homeassistant/components/websocket_api.py b/homeassistant/components/websocket_api.py index 09f8699f5d1..70b35e00247 100644 --- a/homeassistant/components/websocket_api.py +++ b/homeassistant/components/websocket_api.py @@ -204,7 +204,6 @@ class ActiveConnection: self.hass = hass self.request = request self.wsock = None - self.socket_task = None self.event_listeners = {} def debug(self, message1, message2=''): @@ -220,34 +219,6 @@ class ActiveConnection: self.debug('Sending', message) self.wsock.send_json(message, dumps=JSON_DUMP) - @callback - def _cancel_connection(self, event): - """Cancel this connection.""" - self.socket_task.cancel() - - @asyncio.coroutine - def _call_service_helper(self, msg): - """Helper to call a service and fire complete message.""" - yield from self.hass.services.async_call(msg['domain'], msg['service'], - msg['service_data'], True) - try: - self.send_message(result_message(msg['id'])) - except RuntimeError: - # Socket has been closed. - pass - - @callback - def _forward_event(self, iden, event): - """Helper to forward events to websocket.""" - if event.event_type == EVENT_TIME_CHANGED: - return - - try: - self.send_message(event_message(iden, event)) - except RuntimeError: - # Socket has been closed. - pass - @asyncio.coroutine def handle(self): """Handle the websocket connection.""" @@ -255,9 +226,15 @@ class ActiveConnection: yield from wsock.prepare(self.request) # Set up to cancel this connection when Home Assistant shuts down - self.socket_task = asyncio.Task.current_task(loop=self.hass.loop) - self.hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, - self._cancel_connection) + socket_task = asyncio.Task.current_task(loop=self.hass.loop) + + @callback + def cancel_connection(event): + """Cancel this connection.""" + socket_task.cancel() + + unsub_stop = self.hass.bus.async_listen(EVENT_HOMEASSISTANT_STOP, + cancel_connection) self.debug('Connected') @@ -351,6 +328,8 @@ class ActiveConnection: _LOGGER.exception(error) finally: + unsub_stop() + for unsub in self.event_listeners.values(): unsub() @@ -363,8 +342,20 @@ class ActiveConnection: """Handle subscribe events command.""" msg = SUBSCRIBE_EVENTS_MESSAGE_SCHEMA(msg) + @callback + def forward_events(event): + """Helper to forward events to websocket.""" + if event.event_type == EVENT_TIME_CHANGED: + return + + try: + self.send_message(event_message(msg['id'], event)) + except RuntimeError: + # Socket has been closed. + pass + self.event_listeners[msg['id']] = self.hass.bus.async_listen( - msg['event_type'], partial(self._forward_event, msg['id'])) + msg['event_type'], forward_events) self.send_message(result_message(msg['id'])) @@ -386,7 +377,18 @@ class ActiveConnection: """Handle call service command.""" msg = CALL_SERVICE_MESSAGE_SCHEMA(msg) - self.hass.async_add_job(self._call_service_helper(msg)) + @asyncio.coroutine + def call_service_helper(msg): + """Helper to call a service and fire complete message.""" + yield from self.hass.services.async_call( + msg['domain'], msg['service'], msg['service_data'], True) + try: + self.send_message(result_message(msg['id'])) + except RuntimeError: + # Socket has been closed. + pass + + self.hass.async_add_job(call_service_helper(msg)) def handle_get_states(self, msg): """Handle get states command.""" From 8afd30b7d45f1dd6f7c9bbc9a07fd51a51ba1bf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Tue, 6 Dec 2016 03:04:04 +0100 Subject: [PATCH 036/141] fix setting battery in device_tracker (#4756) --- homeassistant/components/device_tracker/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index 7c4c74708db..d497ea4c314 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -421,7 +421,8 @@ class Device(Entity): self.host_name = host_name self.location_name = location_name self.gps_accuracy = gps_accuracy or 0 - + if battery: + self.battery = battery if attributes: self._attributes.update(attributes) From 776455030fd7b2a8321af8842cdd7943325550f1 Mon Sep 17 00:00:00 2001 From: Adam Mills Date: Mon, 5 Dec 2016 21:07:04 -0500 Subject: [PATCH 037/141] Fix media_image_urls for universal media player (#4765) * Fix media_image_urls for universal media player * Linter fixes --- .../components/media_player/universal.py | 11 ++++++++ .../components/media_player/test_universal.py | 26 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/homeassistant/components/media_player/universal.py b/homeassistant/components/media_player/universal.py index cedaeed4985..85a3eb42aa5 100644 --- a/homeassistant/components/media_player/universal.py +++ b/homeassistant/components/media_player/universal.py @@ -263,6 +263,17 @@ class UniversalMediaPlayer(MediaPlayerDevice): """Image url of current playing media.""" return self._child_attr(ATTR_ENTITY_PICTURE) + @property + def entity_picture(self): + """ + Return image of the media playing. + + The universal media player doesn't use the parent class logic, since + the url is coming from child entity pictures which have already been + sent through the API proxy. + """ + return self.media_image_url + @property def media_title(self): """Title of current playing media.""" diff --git a/tests/components/media_player/test_universal.py b/tests/components/media_player/test_universal.py index 76e80f8236e..ff70fe36a17 100644 --- a/tests/components/media_player/test_universal.py +++ b/tests/components/media_player/test_universal.py @@ -28,6 +28,7 @@ class MockMediaPlayer(media_player.MediaPlayerDevice): self._supported_media_commands = 0 self._source = None self._tracks = 12 + self._media_image_url = None self.service_calls = { 'turn_on': mock_service( @@ -92,6 +93,11 @@ class MockMediaPlayer(media_player.MediaPlayerDevice): """Supported media commands flag.""" return self._supported_media_commands + @property + def media_image_url(self): + """Image url of current playing media.""" + return self._media_image_url + def turn_on(self): """Mock turn_on function.""" self._state = STATE_UNKNOWN @@ -400,6 +406,26 @@ class TestMediaPlayer(unittest.TestCase): ump.update() self.assertEqual(1, ump.volume_level) + def test_media_image_url(self): + """Test media_image_url property.""" + TEST_URL = "test_url" + config = self.config_children_only + universal.validate_config(config) + + ump = universal.UniversalMediaPlayer(self.hass, **config) + ump.entity_id = media_player.ENTITY_ID_FORMAT.format(config['name']) + ump.update() + + self.assertEqual(None, ump.media_image_url) + + self.mock_mp_1._state = STATE_PLAYING + self.mock_mp_1._media_image_url = TEST_URL + self.mock_mp_1.update_ha_state() + ump.update() + # mock_mp_1 will convert the url to the api proxy url. This test + # ensures ump passes through the same url without an additional proxy. + self.assertEqual(self.mock_mp_1.entity_picture, ump.entity_picture) + def test_is_volume_muted_children_only(self): """Test is volume muted property w/ children only.""" config = self.config_children_only From 81d38c34631e1418000c9ed08764985cfab07bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Oldag?= Date: Tue, 6 Dec 2016 06:12:24 +0100 Subject: [PATCH 038/141] Add flic smart button component (#4681) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added component for flic smart buttons. * Apply home-assistant coding styles. * Fixed flic configuration. * Made logging for scanning for new buttons less verbose. * Fixed flic event data. * Follow async conventions. * Added new requirements to requirements_all.txt. * Added flic component to .coveragerc * Updated flic threshold configuration key names. * Flic devices are now removed when they disconnect. * Include review feedback. * Fixed stopping of clients in flic component when home assistant is stopped. * Updated flic component by integrating input of #4738. Use library method to determine click type. Merge three click events into single one with click_type parameter. * Use a single client for both handling click events and scanning for new buttons. * Renamed flic ‘auto_scan’ configuration variable to ‘discovery’ using HA constants. --- .coveragerc | 1 + .../components/binary_sensor/flic.py | 196 ++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 200 insertions(+) create mode 100644 homeassistant/components/binary_sensor/flic.py diff --git a/.coveragerc b/.coveragerc index 5dcc37e1402..0d34382659b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -122,6 +122,7 @@ omit = homeassistant/components/alarm_control_panel/simplisafe.py homeassistant/components/binary_sensor/arest.py homeassistant/components/binary_sensor/concord232.py + homeassistant/components/binary_sensor/flic.py homeassistant/components/binary_sensor/rest.py homeassistant/components/browser.py homeassistant/components/camera/amcrest.py diff --git a/homeassistant/components/binary_sensor/flic.py b/homeassistant/components/binary_sensor/flic.py new file mode 100644 index 00000000000..63323155d31 --- /dev/null +++ b/homeassistant/components/binary_sensor/flic.py @@ -0,0 +1,196 @@ +"""Contains functionality to use flic buttons as a binary sensor.""" +import asyncio +import logging + +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.const import ( + CONF_HOST, CONF_PORT, CONF_DISCOVERY, EVENT_HOMEASSISTANT_STOP) +from homeassistant.components.binary_sensor import ( + BinarySensorDevice, PLATFORM_SCHEMA) +from homeassistant.util.async import run_callback_threadsafe + + +REQUIREMENTS = ['https://github.com/soldag/pyflic/archive/0.4.zip#pyflic==0.4'] + +_LOGGER = logging.getLogger(__name__) + + +EVENT_NAME = "flic_click" +EVENT_DATA_NAME = "button_name" +EVENT_DATA_ADDRESS = "button_address" +EVENT_DATA_TYPE = "click_type" + +# Validation of the user's configuration +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_HOST, default='localhost'): cv.string, + vol.Optional(CONF_PORT, default=5551): cv.port, + vol.Optional(CONF_DISCOVERY, default=True): cv.boolean +}) + + +@asyncio.coroutine +def async_setup_platform(hass, config, async_add_entities, + discovery_info=None): + """Setup the flic platform.""" + import pyflic + + # Initialize flic client responsible for + # connecting to buttons and retrieving events + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + discovery = config.get(CONF_DISCOVERY) + + try: + client = pyflic.FlicClient(host, port) + except ConnectionRefusedError: + _LOGGER.error("Failed to connect to flic server.") + return + + def new_button_callback(address): + """Setup newly verified button as device in home assistant.""" + hass.add_job(async_setup_button(hass, config, async_add_entities, + client, address)) + + client.on_new_verified_button = new_button_callback + if discovery: + start_scanning(hass, config, async_add_entities, client) + + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, + lambda event: client.close()) + hass.loop.run_in_executor(None, client.handle_events) + + # Get addresses of already verified buttons + addresses = yield from async_get_verified_addresses(client) + if addresses: + for address in addresses: + yield from async_setup_button(hass, config, async_add_entities, + client, address) + + +def start_scanning(hass, config, async_add_entities, client): + """Start a new flic client for scanning & connceting to new buttons.""" + import pyflic + + scan_wizard = pyflic.ScanWizard() + + def scan_completed_callback(scan_wizard, result, address, name): + """Restart scan wizard to constantly check for new buttons.""" + if result == pyflic.ScanWizardResult.WizardSuccess: + _LOGGER.info("Found new button (%s)", address) + elif result != pyflic.ScanWizardResult.WizardFailedTimeout: + _LOGGER.warning("Failed to connect to button (%s). Reason: %s", + address, result) + + # Restart scan wizard + start_scanning(hass, config, async_add_entities, client) + + scan_wizard.on_completed = scan_completed_callback + client.add_scan_wizard(scan_wizard) + + +@asyncio.coroutine +def async_setup_button(hass, config, async_add_entities, client, address): + """Setup single button device.""" + button = FlicButton(hass, client, address) + _LOGGER.info("Connected to button (%s)", address) + + yield from async_add_entities([button]) + + +@asyncio.coroutine +def async_get_verified_addresses(client): + """Retrieve addresses of verified buttons.""" + future = asyncio.Future() + loop = asyncio.get_event_loop() + + def get_info_callback(items): + """Set the addressed of connected buttons as result of the future.""" + addresses = items["bd_addr_of_verified_buttons"] + run_callback_threadsafe(loop, future.set_result, addresses) + client.get_info(get_info_callback) + + return future + + +class FlicButton(BinarySensorDevice): + """Representation of a flic button.""" + + def __init__(self, hass, client, address): + """Initialize the flic button.""" + import pyflic + + self._hass = hass + self._address = address + self._is_down = False + self._click_types = { + pyflic.ClickType.ButtonSingleClick: "single", + pyflic.ClickType.ButtonDoubleClick: "double", + pyflic.ClickType.ButtonHold: "hold", + } + + # Initialize connection channel + self._channel = pyflic.ButtonConnectionChannel(self._address) + self._channel.on_button_up_or_down = self._on_up_down + self._channel.on_button_single_or_double_click_or_hold = self._on_click + client.add_connection_channel(self._channel) + + @property + def name(self): + """Return the name of the device.""" + return "flic_%s" % self.address.replace(":", "") + + @property + def address(self): + """Return the bluetooth address of the device.""" + return self._address + + @property + def is_on(self): + """Return true if sensor is on.""" + return self._is_down + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def state_attributes(self): + """Return device specific state attributes.""" + attr = super(FlicButton, self).state_attributes + attr["address"] = self.address + + return attr + + def _on_up_down(self, channel, click_type, was_queued, time_diff): + """Update device state, if event was not queued.""" + import pyflic + + if was_queued: + return + + self._is_down = click_type == pyflic.ClickType.ButtonDown + self.schedule_update_ha_state() + + def _on_click(self, channel, click_type, was_queued, time_diff): + """Fire click event, if event was not queued.""" + if was_queued: + return + + self._hass.bus.fire(EVENT_NAME, { + EVENT_DATA_NAME: self.name, + EVENT_DATA_ADDRESS: self.address, + EVENT_DATA_TYPE: self._click_types[click_type] + }) + + def _connection_status_changed(self, channel, + connection_status, disconnect_reason): + """Remove device, if button disconnects.""" + import pyflic + + if connection_status == pyflic.ConnectionStatus.Disconnected: + _LOGGER.info("Button (%s) disconnected. Reason: %s", + self.address, disconnect_reason) + self.remove() diff --git a/requirements_all.txt b/requirements_all.txt index 622faa3719d..0cae8b32af1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -241,6 +241,9 @@ https://github.com/robbiet480/pygtfs/archive/00546724e4bbcb3053110d844ca44e22462 # homeassistant.components.scene.hunterdouglas_powerview https://github.com/sander76/powerviewApi/archive/246e782d60d5c0addcc98d7899a0186f9d5640b0.zip#powerviewApi==0.3.15 +# homeassistant.components.binary_sensor.flic +https://github.com/soldag/pyflic/archive/0.4.zip#pyflic==0.4 + # homeassistant.components.light.osramlightify https://github.com/tfriedel/python-lightify/archive/d6eadcf311e6e21746182d1480e97b350dda2b3e.zip#lightify==1.0.4 From 8c628071f30ae7c6822244011c489b8b648e46ae Mon Sep 17 00:00:00 2001 From: Hugo Dupras Date: Tue, 6 Dec 2016 06:35:33 +0100 Subject: [PATCH 039/141] Add support for Netatmo tags (#4761) * Add support for Netatmo Welcome Tags Signed-off-by: Hugo D. (jabesq) * Add size parameter for WelcomeData * minor fixes * Add Throttling mechanism for update event This will prevent to reach the API limit Signed-off-by: Hugo D. (jabesq) * Change scan interval for Netatmo Binary sensors Signed-off-by: Hugo D. (jabesq) * Minor fixes Signed-off-by: Hugo D. (jabesq) * Update netatmo.py --- .../components/binary_sensor/netatmo.py | 41 +++++++++++++++---- homeassistant/components/netatmo.py | 24 +++++++++-- requirements_all.txt | 2 +- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/binary_sensor/netatmo.py b/homeassistant/components/binary_sensor/netatmo.py index 93b3bb5817c..94ef0faaad0 100644 --- a/homeassistant/components/binary_sensor/netatmo.py +++ b/homeassistant/components/binary_sensor/netatmo.py @@ -23,9 +23,11 @@ _LOGGER = logging.getLogger(__name__) # These are the available sensors mapped to binary_sensor class SENSOR_TYPES = { - "Someone known": "motion", - "Someone unknown": "motion", - "Motion": "motion", + "Someone known": 'occupancy', + "Someone unknown": 'motion', + "Motion": 'motion', + "Tag Vibration": 'vibration', + "Tag Open": 'opening', } CONF_HOME = 'home' @@ -48,6 +50,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): home = config.get(CONF_HOME, None) timeout = config.get(CONF_TIMEOUT, 15) + module_name = None + import lnetatmo try: data = WelcomeData(netatmo.NETATMO_AUTH, home) @@ -64,23 +68,35 @@ def setup_platform(hass, config, add_devices, discovery_info=None): camera_name not in config[CONF_CAMERAS]: continue for variable in sensors: - add_devices([WelcomeBinarySensor(data, camera_name, home, timeout, - variable)]) + if variable in ('Tag Vibration', 'Tag Open'): + continue + add_devices([WelcomeBinarySensor(data, camera_name, module_name, + home, timeout, variable)]) + + for module_name in data.get_module_names(camera_name): + for variable in sensors: + if variable in ('Tag Vibration', 'Tag Open'): + add_devices([WelcomeBinarySensor(data, camera_name, + module_name, home, + timeout, variable)]) class WelcomeBinarySensor(BinarySensorDevice): """Represent a single binary sensor in a Netatmo Welcome device.""" - def __init__(self, data, camera_name, home, timeout, sensor): + def __init__(self, data, camera_name, module_name, home, timeout, sensor): """Setup for access to the Netatmo camera events.""" self._data = data self._camera_name = camera_name + self._module_name = module_name self._home = home self._timeout = timeout if home: self._name = home + ' / ' + camera_name else: self._name = camera_name + if module_name: + self._name += ' / ' + module_name self._sensor_name = sensor self._name += ' ' + sensor camera_id = data.welcomedata.cameraByName(camera=camera_name, @@ -112,7 +128,7 @@ class WelcomeBinarySensor(BinarySensorDevice): def update(self): """Request an update from the Netatmo API.""" self._data.update() - self._data.welcomedata.updateEvent(home=self._data.home) + self._data.update_event() if self._sensor_name == "Someone known": self._state =\ @@ -129,5 +145,16 @@ class WelcomeBinarySensor(BinarySensorDevice): self._data.welcomedata.motionDetected(self._home, self._camera_name, self._timeout*60) + elif self._sensor_name == "Tag Vibration": + self._state =\ + self._data.welcomedata.moduleMotionDetected(self._home, + self._module_name, + self._camera_name, + self._timeout*60) + elif self._sensor_name == "Tag Open": + self._state =\ + self._data.welcomedata.moduleOpened(self._home, + self._module_name, + self._camera_name) else: return None diff --git a/homeassistant/components/netatmo.py b/homeassistant/components/netatmo.py index d6e0101e4e0..3bb98a00b87 100644 --- a/homeassistant/components/netatmo.py +++ b/homeassistant/components/netatmo.py @@ -18,7 +18,7 @@ from homeassistant.util import Throttle REQUIREMENTS = [ 'https://github.com/jabesq/netatmo-api-python/archive/' - 'v0.7.0.zip#lnetatmo==0.7.0'] + 'v0.8.0.zip#lnetatmo==0.8.0'] _LOGGER = logging.getLogger(__name__) @@ -30,6 +30,7 @@ NETATMO_AUTH = None DEFAULT_DISCOVERY = True MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10) +MIN_TIME_BETWEEN_EVENT_UPDATES = timedelta(seconds=10) CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ @@ -72,10 +73,11 @@ class WelcomeData(object): self.auth = auth self.welcomedata = None self.camera_names = [] + self.module_names = [] self.home = home def get_camera_names(self): - """Return all module available on the API as a list.""" + """Return all camera available on the API as a list.""" self.camera_names = [] self.update() if not self.home: @@ -87,8 +89,24 @@ class WelcomeData(object): self.camera_names.append(camera['name']) return self.camera_names + def get_module_names(self, camera_name): + """Return all module available on the API as a list.""" + self.module_names = [] + self.update() + cam_id = self.welcomedata.cameraByName(camera=camera_name, + home=self.home)['id'] + for module in self.welcomedata.modules.values(): + if cam_id == module['cam_id']: + self.module_names.append(module['name']) + return self.module_names + @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Call the Netatmo API to update the data.""" import lnetatmo - self.welcomedata = lnetatmo.WelcomeData(self.auth) + self.welcomedata = lnetatmo.WelcomeData(self.auth, size=100) + + @Throttle(MIN_TIME_BETWEEN_EVENT_UPDATES) + def update_event(self): + """Call the Netatmo API to update the list of events.""" + self.welcomedata.updateEvent(home=self.home) diff --git a/requirements_all.txt b/requirements_all.txt index 0cae8b32af1..d468f2aa863 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -205,7 +205,7 @@ https://github.com/danieljkemp/onkyo-eiscp/archive/python3.zip#onkyo-eiscp==0.9. # https://github.com/deisi/fritzconnection/archive/b5c14515e1c8e2652b06b6316a7f3913df942841.zip#fritzconnection==0.4.6 # homeassistant.components.netatmo -https://github.com/jabesq/netatmo-api-python/archive/v0.7.0.zip#lnetatmo==0.7.0 +https://github.com/jabesq/netatmo-api-python/archive/v0.8.0.zip#lnetatmo==0.8.0 # homeassistant.components.neato https://github.com/jabesq/pybotvac/archive/v0.0.1.zip#pybotvac==0.0.1 From 8ca2345fd4fde5b6ecc924a03c9338f05474ac51 Mon Sep 17 00:00:00 2001 From: Caleb Date: Mon, 5 Dec 2016 23:35:54 -0600 Subject: [PATCH 040/141] Pyunifi dep (#4754) * change unifi dependency to pyunifi * Change dependency to fix #4336 * Run gen_requirements_all.py script * Changed import statement to reflect new package * Updated test_unifiy.py with different module * Update requirements_all.txt --- homeassistant/components/device_tracker/unifi.py | 4 ++-- requirements_all.txt | 6 +++--- tests/components/device_tracker/test_unifi.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/device_tracker/unifi.py b/homeassistant/components/device_tracker/unifi.py index e139775e031..ab84eb22e04 100644 --- a/homeassistant/components/device_tracker/unifi.py +++ b/homeassistant/components/device_tracker/unifi.py @@ -14,7 +14,7 @@ from homeassistant.components.device_tracker import DOMAIN, PLATFORM_SCHEMA from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD # Unifi package doesn't list urllib3 as a requirement -REQUIREMENTS = ['urllib3', 'unifi==1.2.5'] +REQUIREMENTS = ['urllib3', 'pyunifi==1.3'] _LOGGER = logging.getLogger(__name__) CONF_PORT = 'port' @@ -34,7 +34,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ def get_scanner(hass, config): """Setup Unifi device_tracker.""" - from unifi.controller import Controller + from pyunifi.controller import Controller host = config[DOMAIN].get(CONF_HOST) username = config[DOMAIN].get(CONF_USERNAME) diff --git a/requirements_all.txt b/requirements_all.txt index d468f2aa863..6f1ca5eb4e1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -479,6 +479,9 @@ python-twitch==1.3.0 # homeassistant.components.wink python-wink==0.11.0 +# homeassistant.components.device_tracker.unifi +pyunifi==1.3 + # homeassistant.components.keyboard # pyuserinput==0.1.11 @@ -569,9 +572,6 @@ twilio==5.4.0 # homeassistant.components.sensor.uber uber_rides==0.2.7 -# homeassistant.components.device_tracker.unifi -unifi==1.2.5 - # homeassistant.components.device_tracker.unifi urllib3 diff --git a/tests/components/device_tracker/test_unifi.py b/tests/components/device_tracker/test_unifi.py index 5482740ce11..12d296959dc 100644 --- a/tests/components/device_tracker/test_unifi.py +++ b/tests/components/device_tracker/test_unifi.py @@ -3,7 +3,7 @@ import unittest from unittest import mock import urllib -from unifi import controller +from pyunifi import controller import voluptuous as vol from tests.common import get_test_home_assistant From a11b68c560d91cfb1af3b94b8dd088496d66a77c Mon Sep 17 00:00:00 2001 From: dasos Date: Tue, 6 Dec 2016 05:37:05 +0000 Subject: [PATCH 041/141] Fix connection check (#4732) * Fix connection check * Release instead * Remove if * Update hook.py --- homeassistant/components/switch/hook.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/switch/hook.py b/homeassistant/components/switch/hook.py index eba64c6aeb1..689ab675b5f 100644 --- a/homeassistant/components/switch/hook.py +++ b/homeassistant/components/switch/hook.py @@ -50,7 +50,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): return False finally: if response is not None: - yield from response.close() + yield from response.release() try: token = data['data']['token'] @@ -72,7 +72,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): return False finally: if response is not None: - yield from response.close() + yield from response.release() yield from async_add_devices( HookSmartHome( @@ -127,7 +127,7 @@ class HookSmartHome(SwitchDevice): finally: if response is not None: - yield from response.close() + yield from response.release() _LOGGER.debug("Got: %s", data) return data['return_value'] == '1' From 64290d74f09c9df66f116894dc19dad92d908b0c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 5 Dec 2016 21:40:34 -0800 Subject: [PATCH 042/141] Update frontend --- homeassistant/components/frontend/version.py | 2 +- .../frontend/www_static/frontend.html | 4 ++-- .../frontend/www_static/frontend.html.gz | Bin 130456 -> 130476 bytes .../www_static/home-assistant-polymer | 2 +- .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2325 -> 2326 bytes 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 837fdd0e1fe..14650b47cb7 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -2,7 +2,7 @@ FINGERPRINTS = { "core.js": "5dfb2d3e567fad37af0321d4b29265ed", - "frontend.html": "6a89b74ab2b76c7d28fad2aea9444ec2", + "frontend.html": "d4f164e559944b8abc560d7b46131714", "mdi.html": "46a76f877ac9848899b8ed382427c16f", "micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a", "panels/ha-panel-dev-event.html": "c2d5ec676be98d4474d19f94d0262c1e", diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index d0a3e75d8db..54b9cc4d5e4 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -1,5 +1,5 @@ \ No newline at end of file +},customStyle:null,getComputedStyleValue:function(e){return!i&&this._styleProperties&&this._styleProperties[e]||getComputedStyle(this).getPropertyValue(e)},_setupStyleProperties:function(){this.customStyle={},this._styleCache=null,this._styleProperties=null,this._scopeSelector=null,this._ownStyleProperties=null,this._customStyle=null},_needsStyleProperties:function(){return Boolean(!i&&this._ownStylePropertyNames&&this._ownStylePropertyNames.length)},_validateApplyShim:function(){if(this.__applyShimInvalid){Polymer.ApplyShim.transform(this._styles,this.__proto__);var e=n.elementStyles(this);if(s){var t=this._template.content.querySelector("style");t&&(t.textContent=e)}else{var r=this._scopeStyle&&this._scopeStyle.nextSibling;r&&(r.textContent=e)}}},_beforeAttached:function(){this._scopeSelector&&!this.__stylePropertiesInvalid||!this._needsStyleProperties()||(this.__stylePropertiesInvalid=!1,this._updateStyleProperties())},_findStyleHost:function(){for(var e,t=this;e=Polymer.dom(t).getOwnerRoot();){if(Polymer.isInstance(e.host))return e.host;t=e.host}return r},_updateStyleProperties:function(){var e,n=this._findStyleHost();n._styleProperties||n._computeStyleProperties(),n._styleCache||(n._styleCache=new Polymer.StyleCache);var r=t.propertyDataFromStyles(n._styles,this),i=!this.__notStyleScopeCacheable;i&&(r.key.customStyle=this.customStyle,e=n._styleCache.retrieve(this.is,r.key,this._styles));var a=Boolean(e);a?this._styleProperties=e._styleProperties:this._computeStyleProperties(r.properties),this._computeOwnStyleProperties(),a||(e=o.retrieve(this.is,this._ownStyleProperties,this._styles));var l=Boolean(e)&&!a,c=this._applyStyleProperties(e);a||(c=c&&s?c.cloneNode(!0):c,e={style:c,_scopeSelector:this._scopeSelector,_styleProperties:this._styleProperties},i&&(r.key.customStyle={},this.mixin(r.key.customStyle,this.customStyle),n._styleCache.store(this.is,e,r.key,this._styles)),l||o.store(this.is,Object.create(e),this._ownStyleProperties,this._styles))},_computeStyleProperties:function(e){var n=this._findStyleHost();n._styleProperties||n._computeStyleProperties();var r=Object.create(n._styleProperties),s=t.hostAndRootPropertiesForScope(this);this.mixin(r,s.hostProps),e=e||t.propertyDataFromStyles(n._styles,this).properties,this.mixin(r,e),this.mixin(r,s.rootProps),t.mixinCustomStyle(r,this.customStyle),t.reify(r),this._styleProperties=r},_computeOwnStyleProperties:function(){for(var e,t={},n=0;n0&&l.push(t);return[{removed:a,added:l}]}},Polymer.Collection.get=function(e){return Polymer._collections.get(e)||new Polymer.Collection(e)},Polymer.Collection.applySplices=function(e,t){var n=Polymer._collections.get(e);return n?n._applySplices(t):null},Polymer({is:"dom-repeat",extends:"template",_template:null,properties:{items:{type:Array},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},sort:{type:Function,observer:"_sortChanged"},filter:{type:Function,observer:"_filterChanged"},observe:{type:String,observer:"_observeChanged"},delay:Number,renderedItemCount:{type:Number,notify:!0,readOnly:!0},initialCount:{type:Number,observer:"_initializeChunking"},targetFramerate:{type:Number,value:20},_targetFrameTime:{type:Number,computed:"_computeFrameTime(targetFramerate)"}},behaviors:[Polymer.Templatizer],observers:["_itemsChanged(items.*)"],created:function(){this._instances=[],this._pool=[],this._limit=1/0;var e=this;this._boundRenderChunk=function(){e._renderChunk()}},detached:function(){this.__isDetached=!0;for(var e=0;e=0;t--){var n=this._instances[t];n.isPlaceholder&&t=this._limit&&(n=this._downgradeInstance(t,n.__key__)),e[n.__key__]=t,n.isPlaceholder||n.__setProperty(this.indexAs,t,!0)}this._pool.length=0,this._setRenderedItemCount(this._instances.length),this.fire("dom-change"),this._tryRenderChunk()},_applyFullRefresh:function(){var e,t=this.collection;if(this._sortFn)e=t?t.getKeys():[];else{e=[];var n=this.items;if(n)for(var r=0;r=r;a--)this._detachAndRemoveInstance(a)},_numericSort:function(e,t){return e-t},_applySplicesUserSort:function(e){for(var t,n,r=this.collection,s={},i=0;i=0;i--){var c=a[i];void 0!==c&&this._detachAndRemoveInstance(c)}var h=this;if(l.length){this._filterFn&&(l=l.filter(function(e){return h._filterFn(r.getItem(e))})),l.sort(function(e,t){return h._sortFn(r.getItem(e),r.getItem(t))});var u=0;for(i=0;i>1,a=this._instances[o].__key__,l=this._sortFn(n.getItem(a),r);if(l<0)e=o+1;else{if(!(l>0)){i=o;break}s=o-1}}return i<0&&(i=s+1),this._insertPlaceholder(i,t),i},_applySplicesArrayOrder:function(e){for(var t,n=0;n=0?(e=this.as+"."+e.substring(n+1),i._notifyPath(e,t,!0)):i.__setProperty(this.as,t,!0))}},itemForElement:function(e){var t=this.modelForElement(e);return t&&t[this.as]},keyForElement:function(e){var t=this.modelForElement(e);return t&&t.__key__},indexForElement:function(e){var t=this.modelForElement(e);return t&&t[this.indexAs]}}),Polymer({is:"array-selector",_template:null,properties:{items:{type:Array,observer:"clearSelection"},multi:{type:Boolean,value:!1,observer:"clearSelection"},selected:{type:Object,notify:!0},selectedItem:{type:Object,notify:!0},toggle:{type:Boolean,value:!1}},clearSelection:function(){if(Array.isArray(this.selected))for(var e=0;e \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/frontend.html.gz b/homeassistant/components/frontend/www_static/frontend.html.gz index 2e509569ab2ffe7c98d3aa9a446f426cc3d9bf52..3bf5bab1b5944da1c6375064d0b6d982ab667b5d 100644 GIT binary patch delta 62822 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 fMYlflq?(1h^*w{TS2 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

l>k?vg57L5S$BgBT}qK>?fnPXR+;W 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 diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 2652823d35b..4697af1b0d9 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 2652823d35b77411988751cc74820dcfc3a0e2ac +Subproject commit 4697af1b0d96e7a21454539888c68189668fa80d diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index 25535a72081..b125336669c 100644 --- a/homeassistant/components/frontend/www_static/service_worker.js +++ b/homeassistant/components/frontend/www_static/service_worker.js @@ -1 +1 @@ -"use strict";function setOfCachedUrls(e){return e.keys().then(function(e){return e.map(function(e){return e.url})}).then(function(e){return new Set(e)})}function notificationEventCallback(e,t){firePushCallback({action:t.action,data:t.notification.data,tag:t.notification.tag,type:e},t.notification.data.jwt)}function firePushCallback(e,t){delete e.data.jwt,0===Object.keys(e.data).length&&e.data.constructor===Object&&delete e.data,fetch("/api/notify.html5/callback",{method:"POST",headers:new Headers({"Content-Type":"application/json",Authorization:"Bearer "+t}),body:JSON.stringify(e)})}var precacheConfig=[["/","71255a0807fe2c461c870c5f3aaedc56"],["/frontend/panels/dev-event-c2d5ec676be98d4474d19f94d0262c1e.html","6c55fc819751923ab00c62ae3fbb7222"],["/frontend/panels/dev-info-a9c07bf281fe9791fb15827ec1286825.html","931f9327e368db710fcdf5f7202f2588"],["/frontend/panels/dev-service-b3fe49532c5c03198fafb0c6ed58b76a.html","4194cb43b74108dc6d10354da2fd81fd"],["/frontend/panels/dev-state-65e5f791cc467561719bf591f1386054.html","78158786a6597ef86c3fd6f4985cde92"],["/frontend/panels/dev-template-7d744ab7f7c08b6d6ad42069989de400.html","8a6ee994b1cdb45b081299b8609915ed"],["/frontend/panels/map-1bf6965b24d76db71a1871865cd4a3a2.html","a74c01c2ee68c83c9938af067ec33b81"],["/static/core-5dfb2d3e567fad37af0321d4b29265ed.js","9a50270db7613e3af449f6c773366f4d"],["/static/frontend-6a89b74ab2b76c7d28fad2aea9444ec2.html","db91a94d9dcb88f12188d3d88c1200a2"],["/static/mdi-46a76f877ac9848899b8ed382427c16f.html","a846c4082dd5cffd88ac72cbe943e691"],["static/fonts/roboto/Roboto-Bold.ttf","d329cc8b34667f114a95422aaad1b063"],["static/fonts/roboto/Roboto-Light.ttf","7b5fb88f12bec8143f00e21bc3222124"],["static/fonts/roboto/Roboto-Medium.ttf","fe13e4170719c2fc586501e777bde143"],["static/fonts/roboto/Roboto-Regular.ttf","ac3f799d5bbaf5196fab15ab8de8431c"],["static/icons/favicon-192x192.png","419903b8422586a7e28021bbe9011175"],["static/icons/favicon.ico","04235bda7843ec2fceb1cbe2bc696cf4"],["static/images/card_media_player_bg.png","a34281d1c1835d338a642e90930e61aa"],["static/webcomponents-lite.min.js","b0f32ad3c7749c40d486603f31c9d8b1"]],cacheName="sw-precache-v2--"+(self.registration?self.registration.scope:""),ignoreUrlParametersMatching=[/^utm_/],addDirectoryIndex=function(e,t){var a=new URL(e);return"/"===a.pathname.slice(-1)&&(a.pathname+=t),a.toString()},createCacheKey=function(e,t,a,n){var c=new URL(e);return n&&c.toString().match(n)||(c.search+=(c.search?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(a)),c.toString()},isPathWhitelisted=function(e,t){if(0===e.length)return!0;var a=new URL(t).pathname;return e.some(function(e){return a.match(e)})},stripIgnoredUrlParameters=function(e,t){var a=new URL(e);return a.search=a.search.slice(1).split("&").map(function(e){return e.split("=")}).filter(function(e){return t.every(function(t){return!t.test(e[0])})}).map(function(e){return e.join("=")}).join("&"),a.toString()},hashParamName="_sw-precache",urlsToCacheKeys=new Map(precacheConfig.map(function(e){var t=e[0],a=e[1],n=new URL(t,self.location),c=createCacheKey(n,hashParamName,a,!1);return[n.toString(),c]}));self.addEventListener("install",function(e){e.waitUntil(caches.open(cacheName).then(function(e){return setOfCachedUrls(e).then(function(t){return Promise.all(Array.from(urlsToCacheKeys.values()).map(function(a){if(!t.has(a))return e.add(new Request(a,{credentials:"same-origin"}))}))})}).then(function(){return self.skipWaiting()}))}),self.addEventListener("activate",function(e){var t=new Set(urlsToCacheKeys.values());e.waitUntil(caches.open(cacheName).then(function(e){return e.keys().then(function(a){return Promise.all(a.map(function(a){if(!t.has(a.url))return e.delete(a)}))})}).then(function(){return self.clients.claim()}))}),self.addEventListener("fetch",function(e){if("GET"===e.request.method){var t,a=stripIgnoredUrlParameters(e.request.url,ignoreUrlParametersMatching);t=urlsToCacheKeys.has(a);var n="index.html";!t&&n&&(a=addDirectoryIndex(a,n),t=urlsToCacheKeys.has(a));var c="/";!t&&c&&"navigate"===e.request.mode&&isPathWhitelisted(["^((?!(static|api|local|service_worker.js|manifest.json)).)*$"],e.request.url)&&(a=new URL(c,self.location).toString(),t=urlsToCacheKeys.has(a)),t&&e.respondWith(caches.open(cacheName).then(function(e){return e.match(urlsToCacheKeys.get(a)).then(function(e){if(e)return e;throw Error("The cached response that was expected is missing.")})}).catch(function(t){return console.warn('Couldn\'t serve response for "%s" from cache: %O',e.request.url,t),fetch(e.request)}))}}),self.addEventListener("push",function(e){var t;e.data&&(t=e.data.json(),e.waitUntil(self.registration.showNotification(t.title,t).then(function(e){firePushCallback({type:"received",tag:t.tag,data:t.data},t.data.jwt)})))}),self.addEventListener("notificationclick",function(e){var t;notificationEventCallback("clicked",e),e.notification.close(),e.notification.data&&e.notification.data.url&&(t=e.notification.data.url,t&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var a,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 tH^ChnGi<^|Gf{SBukd%>`rHrhyjUreDC-k z;H+90w5BPfaVC0INmJC-pat_zzuT^@JE_l}sm{n6<4IuaqSFP&>W)79R*|7J) zf-fI_v1-a&@AmlC3N8m9!QcvhwzZ|IO`!|P?SEcgKxJO=vJ_l?cfmK_wJsWXziQ{( z)ob4EJ2gT7;45x8{%==KVAp)ZXZP1}$&uYAXO$O}P|eJII9z`!>k1>WlBRC98-~L@ zalQs4=dLs6%VOM_cNNUdqD;neZG+=qFTl)eb?Ur-_wkeC&w(pw+Ea_}Kl*3)+Idk| z2C*D{LT8;*hcB1q+R^d1wyqri`3i+J#eciClWGAke2t%1t4v`ijqm&-kQ&hSh@mz+P(3BAkd6p9`NWy3al2Dd1nrzhM5z%>s zFQSwwf02<;OQjQ?(U5AIFm_x`3(Z9#VI(3Aah^m}CNhjj&NSBoZ3UGuk)?d2DJFR= zMI4DNCLvQYRV0j(SaGTqTB#np0GJDzhw#Qp8H_$=x_GN;%6hd|Xi6Co@Gc)(Ufy=W!f^+*++fPH;`- zN(#m_p@cCNDaJ7S!jRKF=?hhi;*@8pW?9B%&SJ(ah@c`yW12~l>Ma~BPGuZ2s#GF1 z<_+UAqY_Igjv&o@I5t+J(e1dYMQ!Twe~0d8^lM$Jz!+_9jA$+;6H%NZQiQ}jPhv_r z=Zc6hjeaKTbupWpwX94ex_49nmTVm9Fa%13jIdA%jejQV4X9$ZSPRpD5s66_VuDMm zWrA4|63DVlC_vdi6ZQdStCBZsX&kdZ%X5_o!8LZ0RCDYETrdSJj)>fqR@lBhf7blM zK8&#I{J_7#vYPePn}?Wj2oV~@GoUO)4-xs05RxTFi*%Xn4MTv^ACeoOqDR~q^N;uz@ zb_qh(i)CG5_iaaIVUXC1sxJc(f9i;0m0;q>IVP5hS(=8CMqqNq1m@GZ-*LcOzJRII zUXC`TFuI_lk#pjDl=Am05fppZi>?-;j_keO|q)6#SUp%@~%KEjjV2rNPf1UL#*k`mqD)e+k)^2TN|| z6-p0UWI}L9#2XIXyXBLq@q8Yb`eR3Vu6OIp2C(gQW75CiYEPTb{i@d}4>b;|;ZW{K z!imX}dga~RxH4#wY32N6x_x}+3>^!@2~@IH@cF~57n{Ji#yfGQ&O>jw=lOEa+@gJt zzI>TuC`&{c)IEF(?b<;Ff7WA(*BkpJoa_TA<(s!tzxY zOtlxyKNcyJ)*~|AJgj3yyr9MT#kh!+cYOX_e=~LL5UPt3H9z#B32@|SuI^r$&8sKa zxuC@X^(;L1x>5G1u5WcwZB+HoXxhE}ne%quVbGV!*PS|Xd>oeBlMx0Kf1l$IIrpo( z$oXB7m32SpVSY^aQ`oKcZNe;mLN@51RXfJ}^8D8GCY?O2yKXLjZIh}(Oq~MfSR6+k zf7dbyE_q=-SEeZ4&Vx3<`mWq_|H-7{uSr(Rq@Rt{hpFq_ekM?mwE1bW-{N!}4t?A~^y zw+CH#jETI7ncj~=pGI8+t)^HONJ{-oHhF?4yUG&G^nkWp%N_nPVZAgtMcV3w$l=hb zaAug<1ljiyDPcG~==$!N^SkRld*b#)e}gB<8`~1foAuG;>t)@1hX$$sX2GjMTUqu@ zh{fXl^)EOh>_O78f8@5s$a^hjw`Cml$T#)~+(3)erM?tq{^#?wXPNu*XVCHB;Xcd> z*ke5zWQ@KxH)T>fe|9)x)7HzoGp=&%{|I#`G+pl^He@+L#ynDKjHnQXT3Shh3 z6~yt1SgzXn1C3+S-zQ-3kS*3X6|F5jf45&eFqF;f%eOn%A}&&5VMGoJdz&gHn-y_Sq z1@~aNN9}<{cN?BHoDaV1vwWu)uiILey3etJuEDv)Hc?+X58ab>bCF+7FjuhV!U_M| zW>}l>lM@fKx^*~Olkrv1t-0O=cWlhCwf3b`z4`3$jr-@q bf%xr* Date: Tue, 6 Dec 2016 00:20:21 -0600 Subject: [PATCH 043/141] Match uppercase MAC addresses in asuswrt 'arp -n' output (#4742) (#4764) --- homeassistant/components/device_tracker/asuswrt.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/device_tracker/asuswrt.py b/homeassistant/components/device_tracker/asuswrt.py index 2eced1b4dd4..4e860846f8e 100644 --- a/homeassistant/components/device_tracker/asuswrt.py +++ b/homeassistant/components/device_tracker/asuswrt.py @@ -286,8 +286,10 @@ class AsusWrtDeviceScanner(object): # match mac addresses to IP addresses in ARP table for arp in result.arp: - if match.group('mac').lower() in arp.decode('utf-8'): - arp_match = _ARP_REGEX.search(arp.decode('utf-8')) + if match.group('mac').lower() in \ + arp.decode('utf-8').lower(): + arp_match = _ARP_REGEX.search( + arp.decode('utf-8').lower()) if not arp_match: _LOGGER.warning('Could not parse arp row: %s', arp) continue From fa0dbaf065af549e5211c350a68cb9017fbdd919 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 5 Dec 2016 23:39:22 -0800 Subject: [PATCH 044/141] 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 d968e1d0110f949eb43bd4bbfa15dfdfea85b1e6 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Tue, 6 Dec 2016 13:01:24 +0000 Subject: [PATCH 045/141] Add test to ensure device_tracker records state correctly. (#4776) --- tests/components/device_tracker/test_init.py | 39 ++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/components/device_tracker/test_init.py b/tests/components/device_tracker/test_init.py index 013920985ff..c3087b108e9 100644 --- a/tests/components/device_tracker/test_init.py +++ b/tests/components/device_tracker/test_init.py @@ -458,6 +458,45 @@ class TestComponentsDeviceTracker(unittest.TestCase): timedelta(seconds=0)) assert len(config) == 0 + def test_see_state(self): + """Test device tracker see records state correctly.""" + self.assertTrue(setup_component(self.hass, device_tracker.DOMAIN, + TEST_PLATFORM)) + + params = { + 'mac': 'AA:BB:CC:DD:EE:FF', + 'dev_id': 'some_device', + 'host_name': 'example.com', + 'location_name': 'Work', + 'gps': [.3, .8], + 'gps_accuracy': 1, + 'battery': 100, + 'attributes': { + 'test': 'test', + 'number': 1, + }, + } + + device_tracker.see(self.hass, **params) + self.hass.block_till_done() + + config = device_tracker.load_config(self.yaml_devices, self.hass, + timedelta(seconds=0)) + assert len(config) == 1 + + state = self.hass.states.get('device_tracker.examplecom') + attrs = state.attributes + self.assertEqual(state.state, 'Work') + self.assertEqual(state.object_id, 'examplecom') + self.assertEqual(state.name, 'example.com') + self.assertEqual(attrs['friendly_name'], 'example.com') + self.assertEqual(attrs['battery'], 100) + self.assertEqual(attrs['latitude'], 0.3) + self.assertEqual(attrs['longitude'], 0.8) + self.assertEqual(attrs['test'], 'test') + self.assertEqual(attrs['gps_accuracy'], 1) + self.assertEqual(attrs['number'], 1) + @patch('homeassistant.components.device_tracker._LOGGER.warning') def test_see_failures(self, mock_warning): """Test that the device tracker see failures.""" From 76ff934bd34cb04cf3a028add2a7d6bb572b565f Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Tue, 6 Dec 2016 15:49:59 +0100 Subject: [PATCH 046/141] Move details to docs, update doc strings, and use consts (#4777) --- homeassistant/components/sensor/zamg.py | 145 +++++++----------------- 1 file changed, 38 insertions(+), 107 deletions(-) diff --git a/homeassistant/components/sensor/zamg.py b/homeassistant/components/sensor/zamg.py index d3d64690ef6..6bb9dd0748d 100644 --- a/homeassistant/components/sensor/zamg.py +++ b/homeassistant/components/sensor/zamg.py @@ -1,81 +1,38 @@ """ Sensor for data from Austrian "Zentralanstalt für Meteorologie und Geodynamik". -This is a sensor for the Austrian weather service "Zentralanstalt für -Meteorologie und Geodynamik" (aka ZAMG). - -The configuration should look like this: - - - platform: zamg - station_id: 11035 - monitored_conditions: - - temperature - - humidity - - pressure - - wind_speed - - precipitation - -Recognised conditions are: - - pressure (Pressure at station level) - pressure_sealevel (Pressure at Sea Level) - humidity (Humidity) - wind_speed (Wind Speed) - wind_bearing (Wind Bearing) - wind_max_speed (Top Wind Speed) - wind_max_bearing (Top Wind Bearing) - sun_last_hour (Sun Last Hour Percentage) - temperature (Temperature) - precipitation (Precipitation) - dewpoint (Dew Point) - -The following stations are available in the data set: - - 11010 Linz/Hörsching - 11012 Kremsmünster - 11022 Retz - 11035 Wien/Hohe Warte - 11036 Wien/Schwechat - 11101 Bregenz - 11121 Innsbruck - 11126 Patscherkofel - 11130 Kufstein - 11150 Salzburg - 11155 Feuerkogel - 11157 Aigen im Ennstal - 11171 Mariazell - 11190 Eisenstadt - 11204 Lienz +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.zamg/ """ - import csv -from datetime import timedelta import logging -import requests +from datetime import timedelta +import requests import voluptuous as vol -from homeassistant.components.weather import ( - ATTR_WEATHER_HUMIDITY, ATTR_WEATHER_ATTRIBUTION, - ATTR_WEATHER_PRESSURE, ATTR_WEATHER_TEMPERATURE, - ATTR_WEATHER_WIND_BEARING, ATTR_WEATHER_WIND_SPEED, -) import homeassistant.helpers.config_validation as cv +from homeassistant.components.weather import ( + ATTR_WEATHER_HUMIDITY, ATTR_WEATHER_ATTRIBUTION, ATTR_WEATHER_PRESSURE, + ATTR_WEATHER_TEMPERATURE, ATTR_WEATHER_WIND_BEARING, + ATTR_WEATHER_WIND_SPEED) from homeassistant.const import ( - CONF_MONITORED_CONDITIONS, CONF_NAME, __version__ -) + CONF_MONITORED_CONDITIONS, CONF_NAME, __version__) from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle -DEFAULT_NAME = 'zamg' +ATTR_STATION = 'station' +ATTR_UPDATED = 'updated' ATTRIBUTION = 'Data provided by ZAMG' -# Data source only updates once per hour, so throttle to 30min to have +CONF_STATION_ID = 'station_id' + +DEFAULT_NAME = 'zamg' + +# Data source only updates once per hour, so throttle to 30 min to have # reasonably recent data MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30) -CONF_STATION_ID = "station_id" - VALID_STATION_IDS = ( '11010', '11012', '11022', '11035', '11036', '11101', '11121', '11126', '11130', '11150', '11155', '11157', '11171', '11190', '11204' @@ -102,41 +59,37 @@ SENSOR_TYPES = { } PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Required(CONF_STATION_ID): - vol.All(cv.string, vol.In(VALID_STATION_IDS)), vol.Required(CONF_MONITORED_CONDITIONS): vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), + vol.Required(CONF_STATION_ID): + vol.All(cv.string, vol.In(VALID_STATION_IDS)), + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup platform.""" + """Set up the ZAMG sensor platform.""" station_id = config.get(CONF_STATION_ID) name = config.get(CONF_NAME) logger = logging.getLogger(__name__) probe = ZamgData(station_id=station_id, logger=logger) - sensors = [ZAMGWeather(probe, variable, name) + sensors = [ZamgSensor(probe, variable, name) for variable in config[CONF_MONITORED_CONDITIONS]] add_devices(sensors, True) -class ZAMGWeather(Entity): - """ - I am a weather wrapper for a specific station and a specific attribute. - - Multiple instances (one for each condition) will refer to the same - probe, so things will only get fetched once. - """ +class ZamgSensor(Entity): + """Implementation of a ZAMG sensor.""" def __init__(self, probe, variable, name): - """Init condition sensor.""" + """Initialize the sensor.""" self.probe = probe self.client_name = name self.variable = variable + self.update() def update(self): """Delegate update to probe.""" @@ -144,17 +97,17 @@ class ZAMGWeather(Entity): @property def name(self): - """Build name of sensor.""" + """Return the name of the sensor.""" return '{} {}'.format(self.client_name, self.variable) @property def state(self): - """Return state.""" + """Return the state of the sensor.""" return self.probe.get_data(self.variable) @property def unit_of_measurement(self): - """Unit of measurement.""" + """Return the unit of measurement of this entity, if any.""" return SENSOR_TYPES[self.variable][1] @property @@ -162,38 +115,22 @@ class ZAMGWeather(Entity): """Return the state attributes.""" return { ATTR_WEATHER_ATTRIBUTION: ATTRIBUTION, - "station": self.probe.get_data('station_name'), - "updated": "%s %s" % (self.probe.get_data('update_date'), - self.probe.get_data('update_time')) + ATTR_STATION: self.probe.get_data('station_name'), + ATTR_UPDATED: '{} {}'.format(self.probe.get_data('update_date'), + self.probe.get_data('update_time')), } class ZamgData(object): - """ - I represent weather data for a specific site. - - From the web site: - - Sie beinhalten neben Stationsnummer, Stationsname, Seehöhe der Station, - Messdatum und Messzeit (Lokalzeit) die meteorologischen Messwerte von - Temperatur, Taupunkt, relative Luftfeuchtigkeit, Richtung und - Geschwindigkeit des Windmittels und der Windspitze, Niederschlagssumme - der letzten Stunde, Luftdruck reduziert auf Meeresniveau und Luftdruck - auf Stationsniveau sowie die Sonnenscheindauer der letzten Stunde (in - Prozent). Die Messstationen, die diese Daten liefern, sind über das - Bundesgebiet verteilt und beinhalten alle Landeshauptstädte sowie - die wichtigsten Bergstationen. - """ - - API_URL = "http://www.zamg.ac.at/ogd/" + """The class for handling the data retrieval.""" + API_URL = 'http://www.zamg.ac.at/ogd/' API_FIELDS = { v[2]: (k, v[3]) for k, v in SENSOR_TYPES.items() } - API_HEADERS = { - 'User-Agent': 'home-assistant.zamg/' + __version__, + 'User-Agent': '{} {}'.format('home-assistant.zamg/', __version__), } def __init__(self, logger, station_id): @@ -204,15 +141,10 @@ class ZamgData(object): @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): - """ - Update data set. - - Fetch a new data set from the zamg server, parse it and - update internal state accordingly - """ + """Get the latest data from ZAMG.""" try: - response = requests.get(self.API_URL, - headers=self.API_HEADERS, timeout=15) + response = requests.get( + self.API_URL, headers=self.API_HEADERS, timeout=15) except requests.exceptions.RequestException: self._logger.exception("While fetching data from server") return @@ -224,8 +156,7 @@ class ZamgData(object): content_type = response.headers.get('Content-Type', 'whatever') if content_type != 'text/csv': - self._logger.error("Expected text/csv but got %s", - content_type) + self._logger.error("Expected text/csv but got %s", content_type) return response.encoding = 'UTF8' From 860a12cffbecbfb547dcb3d91f20a162e0445963 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 6 Dec 2016 07:43:11 -0800 Subject: [PATCH 047/141] 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 8826e6a8d0613948669a8784aa76270bf6a2df63 Mon Sep 17 00:00:00 2001 From: Audun Ytterdal Date: Tue, 6 Dec 2016 18:01:47 +0100 Subject: [PATCH 048/141] Add support for telldus in the Docker image. (#4680) * Add support for telldus in the Docker image. Start with -v /tmp/TelldusClient:/tmp/TelldusClient -v /tmp/TelldusEvents:/tmp/TelldusEvents * Merged telldus install with the others * Clean up indenting * Stream apt-key --- Dockerfile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index b42d7edcc89..02e3db616ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,12 @@ WORKDIR /usr/src/app RUN pip3 install --no-cache-dir colorlog cython -# For the nmap tracker, bluetooth tracker, Z-Wave -RUN apt-get update && \ - apt-get install -y --no-install-recommends nmap net-tools cython3 libudev-dev sudo libglib2.0-dev bluetooth libbluetooth-dev && \ +# For the nmap tracker, bluetooth tracker, Z-Wave, tellstick +RUN echo "deb http://download.telldus.com/debian/ stable main" >> /etc/apt/sources.list.d/telldus.list && \ + wget -qO - http://download.telldus.se/debian/telldus-public.key | apt-key add - && \ + apt-get update && \ + apt-get install -y --no-install-recommends nmap net-tools cython3 libudev-dev sudo libglib2.0-dev bluetooth libbluetooth-dev \ + libtelldus-core2 libtelldus-core-dev && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* COPY script/build_python_openzwave script/build_python_openzwave From 9a3fe691b1a52be49dc0da602b7e6a9812da57c7 Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Tue, 6 Dec 2016 23:31:07 -0500 Subject: [PATCH 049/141] 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 6f1ca5eb4e1..bcc9836fdc9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -167,7 +167,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 c40ddf18c79e2149c95a0e9e649869ecd6a80071 Mon Sep 17 00:00:00 2001 From: Adam Mills Date: Wed, 7 Dec 2016 00:03:49 -0500 Subject: [PATCH 050/141] 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 76b79019ce8b7535d5a22d472356b9ee68fbddfa Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 6 Dec 2016 21:47:58 -0800 Subject: [PATCH 051/141] Add faster reviews link to contributing --- CONTRIBUTING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8621851ffb6..3dbc2a7022c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,14 @@ # Contributing to Home Assistant -Everybody is invited and welcome to contribute to Home Assistant. There is a lot to do...if you are not a developer perhaps you would like to help with the documentation on [home-assistant.io](https://home-assistant.io/)? If you are a developer and have devices in your home which aren't working with Home Assistant yet, why not spent a couple of hours and help to integrate them? +Everybody is invited and welcome to contribute to Home Assistant. There is a lot to do...if you are not a developer perhaps you would like to help with the documentation on [home-assistant.io](https://home-assistant.io/)? If you are a developer and have devices in your home which aren't working with Home Assistant yet, why not spent a couple of hours and help to integrate them? The process is straight-forward. + - Read [How to get faster PR reviews](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/faster_reviews.md) by Kubernetes - Fork the Home Assistant [git repository](https://github.com/home-assistant/home-assistant). - Write the code for your device, notification service, sensor, or IoT thing. - Ensure tests work. - Create a Pull Request against the [**dev**](https://github.com/home-assistant/home-assistant/tree/dev) branch of Home Assistant. -Still interested? Then you should take a peak at the [developer documentation](https://home-assistant.io/developers/) to get more details. +Still interested? Then you should take a peak at the [developer documentation](https://home-assistant.io/developers/) to get more details. From 37e3c2a1336a0ae31bde9356f0a7cb7c06618081 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 6 Dec 2016 21:48:44 -0800 Subject: [PATCH 052/141] Contributing: add skip step 0 --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3dbc2a7022c..a63c1400723 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ Everybody is invited and welcome to contribute to Home Assistant. There is a lot The process is straight-forward. - - Read [How to get faster PR reviews](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/faster_reviews.md) by Kubernetes + - Read [How to get faster PR reviews](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/faster_reviews.md) by Kubernetes (but skip step 0) - Fork the Home Assistant [git repository](https://github.com/home-assistant/home-assistant). - Write the code for your device, notification service, sensor, or IoT thing. - Ensure tests work. From 98fe50d5adea8a4322641ed5c23a745065a8766c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 6 Dec 2016 22:30:47 -0800 Subject: [PATCH 053/141] 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 82ad8b0a8fbc978693ef63c4a4ad506f353088fa Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Wed, 7 Dec 2016 03:15:48 -0500 Subject: [PATCH 054/141] round $ to 2 decimals (#4786) --- homeassistant/components/sensor/coinmarketcap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/coinmarketcap.py b/homeassistant/components/sensor/coinmarketcap.py index 61545fa3944..e041352af58 100644 --- a/homeassistant/components/sensor/coinmarketcap.py +++ b/homeassistant/components/sensor/coinmarketcap.py @@ -77,7 +77,7 @@ class CoinMarketCapSensor(Entity): @property def state(self): """Return the state of the sensor.""" - return self._ticker.get('price_usd') + return round(self._ticker.get('price_usd'), 2) @property def unit_of_measurement(self): From d0dcd1bb732c2b260c6fe7fe96d5ff0d2fbb2aee Mon Sep 17 00:00:00 2001 From: Jan Losinski Date: Wed, 7 Dec 2016 14:33:41 +0100 Subject: [PATCH 055/141] Scene: add support for input_select (#4674) This adds support for the scene component to handle input_select devices and set their options. This fixes bug #4673 Signed-off-by: Jan Losinski --- homeassistant/const.py | 4 ++++ homeassistant/helpers/state.py | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index d9191eaedf2..0a014c0b603 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -278,6 +278,8 @@ ATTR_GPS_ACCURACY = 'gps_accuracy' ATTR_ASSUMED_STATE = 'assumed_state' ATTR_STATE = 'state' +ATTR_OPTION = 'option' + # #### SERVICES #### SERVICE_HOMEASSISTANT_STOP = 'stop' SERVICE_HOMEASSISTANT_RESTART = 'restart' @@ -318,6 +320,8 @@ SERVICE_SET_COVER_TILT_POSITION = 'set_cover_tilt_position' SERVICE_STOP_COVER = 'stop_cover' SERVICE_STOP_COVER_TILT = 'stop_cover_tilt' +SERVICE_SELECT_OPTION = 'select_option' + # #### API / REMOTE #### SERVER_PORT = 8123 diff --git a/homeassistant/helpers/state.py b/homeassistant/helpers/state.py index 9980ad11a8d..46b7837dc15 100644 --- a/homeassistant/helpers/state.py +++ b/homeassistant/helpers/state.py @@ -32,7 +32,7 @@ from homeassistant.const import ( SERVICE_CLOSE_COVER, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, STATE_CLOSED, STATE_LOCKED, STATE_OFF, STATE_ON, STATE_OPEN, STATE_PAUSED, STATE_PLAYING, - STATE_UNKNOWN, STATE_UNLOCKED) + STATE_UNKNOWN, STATE_UNLOCKED, SERVICE_SELECT_OPTION, ATTR_OPTION) from homeassistant.core import State from homeassistant.util.async import run_coroutine_threadsafe @@ -58,7 +58,8 @@ SERVICE_ATTRIBUTES = { SERVICE_SET_OPERATION_MODE: [ATTR_OPERATION_MODE], SERVICE_SET_AUX_HEAT: [ATTR_AUX_HEAT], SERVICE_SELECT_SOURCE: [ATTR_INPUT_SOURCE], - SERVICE_SEND_IR_CODE: [ATTR_IR_CODE] + SERVICE_SEND_IR_CODE: [ATTR_IR_CODE], + SERVICE_SELECT_OPTION: [ATTR_OPTION] } # Update this dict when new services are added to HA. From 8295fc8b4c8098931fba3822ce7e302d505f4e64 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Wed, 7 Dec 2016 17:37:35 +0100 Subject: [PATCH 056/141] Pararell execute state restore by domain (#4801) * Pararell execute state restore per domain * fix spell --- homeassistant/helpers/state.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/homeassistant/helpers/state.py b/homeassistant/helpers/state.py index 46b7837dc15..536975c100e 100644 --- a/homeassistant/helpers/state.py +++ b/homeassistant/helpers/state.py @@ -164,11 +164,28 @@ def async_reproduce_state(hass, states, blocking=False): json.dumps(dict(state.attributes), sort_keys=True)) to_call[key].append(state.entity_id) + domain_tasks = {} for (service_domain, service, service_data), entity_ids in to_call.items(): data = json.loads(service_data) data[ATTR_ENTITY_ID] = entity_ids - yield from hass.services.async_call( - service_domain, service, data, blocking) + + if service_domain not in domain_tasks: + domain_tasks[service_domain] = [] + + domain_tasks[service_domain].append( + hass.services.async_call(service_domain, service, data, blocking) + ) + + @asyncio.coroutine + def async_handle_service_calls(coro_list): + """Handle service calls by domain sequence.""" + for coro in coro_list: + yield from coro + + execute_tasks = [async_handle_service_calls(coro_list) + for coro_list in domain_tasks.values()] + if execute_tasks: + yield from asyncio.wait(execute_tasks, loop=hass.loop) def state_as_number(state): From 194b268ae3938b1e80cbac5b984815a5e93f823d Mon Sep 17 00:00:00 2001 From: Keaton Taylor Date: Wed, 7 Dec 2016 23:45:18 -0600 Subject: [PATCH 057/141] Get entity name from entity.name (#4798) Grabbing the ATTR_FRIENDLY_NAME directly produces an error. Instead grab from entity.name. --- homeassistant/components/emulated_hue/hue_api.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/emulated_hue/hue_api.py b/homeassistant/components/emulated_hue/hue_api.py index ed06da9495b..32fb4af071c 100644 --- a/homeassistant/components/emulated_hue/hue_api.py +++ b/homeassistant/components/emulated_hue/hue_api.py @@ -6,8 +6,8 @@ from aiohttp import web from homeassistant import core from homeassistant.const import ( - ATTR_ENTITY_ID, ATTR_FRIENDLY_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON, - STATE_ON, STATE_OFF, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, + ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_ON, + STATE_OFF, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, ) from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_SUPPORTED_FEATURES, SUPPORT_BRIGHTNESS @@ -251,8 +251,7 @@ def entity_to_json(entity, is_on=None, brightness=None): if brightness is None: brightness = 255 if is_on else 0 - name = entity.attributes.get( - ATTR_EMULATED_HUE_NAME, entity.attributes[ATTR_FRIENDLY_NAME]) + name = entity.attributes.get(ATTR_EMULATED_HUE_NAME, entity.name) return { 'state': From 695f062e298cf58ce81ee3c40d0dea837ad6fbef Mon Sep 17 00:00:00 2001 From: R1chardTM Date: Thu, 8 Dec 2016 06:45:43 +0100 Subject: [PATCH 058/141] 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 bcc9836fdc9..27573a2c587 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -167,7 +167,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 2e2b764dbee5ef598d9ff6907925de94b78831e2 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Wed, 7 Dec 2016 23:46:42 -0600 Subject: [PATCH 059/141] Add exception handling when turning on Onkyo receivers (#4813) --- homeassistant/components/media_player/onkyo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/media_player/onkyo.py b/homeassistant/components/media_player/onkyo.py index 5829d119f95..28f8dd1bf6b 100644 --- a/homeassistant/components/media_player/onkyo.py +++ b/homeassistant/components/media_player/onkyo.py @@ -89,7 +89,7 @@ class OnkyoDevice(MediaPlayerDevice): except (ValueError, OSError, AttributeError, AssertionError): if self._receiver.command_socket: self._receiver.command_socket = None - _LOGGER.info('Reseting connection to %s.', self._name) + _LOGGER.info('Resetting connection to %s.', self._name) else: _LOGGER.info('%s is disconnected. Attempting to reconnect.', self._name) @@ -173,7 +173,7 @@ class OnkyoDevice(MediaPlayerDevice): def turn_on(self): """Turn the media player on.""" - self._receiver.power_on() + self.command('system-power on') def select_source(self, source): """Set the input source.""" From 14446c5731e788c67af819234cf158cc9f3c6f16 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 8 Dec 2016 08:36:37 +0000 Subject: [PATCH 060/141] [media_player.sonos] Add stop support. (#4788) --- .../components/media_player/sonos.py | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/media_player/sonos.py b/homeassistant/components/media_player/sonos.py index 1fa1a39633d..c6e9c1e6655 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -15,7 +15,7 @@ from homeassistant.components.media_player import ( ATTR_MEDIA_ENQUEUE, DOMAIN, MEDIA_TYPE_MUSIC, SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK, SUPPORT_SEEK, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_CLEAR_PLAYLIST, - SUPPORT_SELECT_SOURCE, MediaPlayerDevice, PLATFORM_SCHEMA) + SUPPORT_SELECT_SOURCE, MediaPlayerDevice, PLATFORM_SCHEMA, SUPPORT_STOP) from homeassistant.const import ( STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_OFF, ATTR_ENTITY_ID, CONF_HOSTS) @@ -36,9 +36,10 @@ _SOCO_LOGGER.setLevel(logging.ERROR) _REQUESTS_LOGGER = logging.getLogger('requests') _REQUESTS_LOGGER.setLevel(logging.ERROR) -SUPPORT_SONOS = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE |\ - SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | SUPPORT_PLAY_MEDIA |\ - SUPPORT_SEEK | SUPPORT_CLEAR_PLAYLIST | SUPPORT_SELECT_SOURCE +SUPPORT_SONOS = SUPPORT_STOP | SUPPORT_PAUSE | SUPPORT_VOLUME_SET |\ + SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK |\ + SUPPORT_PLAY_MEDIA | SUPPORT_SEEK | SUPPORT_CLEAR_PLAYLIST |\ + SUPPORT_SELECT_SOURCE SERVICE_GROUP_PLAYERS = 'sonos_group_players' SERVICE_UNJOIN = 'sonos_unjoin' @@ -289,6 +290,7 @@ class SonosDevice(MediaPlayerDevice): self._media_next_title = None self._support_previous_track = False self._support_next_track = False + self._support_stop = False self._support_pause = False self._current_track_uri = None self._current_track_is_radio_stream = False @@ -433,6 +435,7 @@ class SonosDevice(MediaPlayerDevice): support_previous_track = False support_next_track = False + support_stop = False support_pause = False if is_playing_tv: @@ -450,6 +453,7 @@ class SonosDevice(MediaPlayerDevice): ) support_previous_track = False support_next_track = False + support_stop = False support_pause = False # for radio streams we set the radio station name as the @@ -506,6 +510,7 @@ class SonosDevice(MediaPlayerDevice): ) support_previous_track = True support_next_track = True + support_stop = True support_pause = True position_info = self._player.avTransport.GetPositionInfo( @@ -583,6 +588,7 @@ class SonosDevice(MediaPlayerDevice): self._current_track_is_radio_stream = is_radio_stream self._support_previous_track = support_previous_track self._support_next_track = support_next_track + self._support_stop = support_stop self._support_pause = support_pause self._is_playing_tv = is_playing_tv self._is_playing_line_in = is_playing_line_in @@ -614,6 +620,7 @@ class SonosDevice(MediaPlayerDevice): self._current_track_is_radio_stream = False self._support_previous_track = False self._support_next_track = False + self._support_stop = False self._support_pause = False self._is_playing_tv = False self._is_playing_line_in = False @@ -774,6 +781,9 @@ class SonosDevice(MediaPlayerDevice): if not self._support_next_track: supported = supported ^ SUPPORT_NEXT_TRACK + if not self._support_stop: + supported = supported ^ SUPPORT_STOP + if not self._support_pause: supported = supported ^ SUPPORT_PAUSE @@ -836,6 +846,13 @@ class SonosDevice(MediaPlayerDevice): else: self._player.play() + def media_stop(self): + """Send stop command.""" + if self._coordinator: + self._coordinator.media_stop() + else: + self._player.stop() + def media_pause(self): """Send pause command.""" if self._coordinator: From c90a1b97605648f9855926b86b147ec4347151c4 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 8 Dec 2016 22:31:23 -0800 Subject: [PATCH 061/141] Update frontend --- homeassistant/components/frontend/version.py | 6 +- .../frontend/www_static/frontend.html | 4 +- .../frontend/www_static/frontend.html.gz | Bin 130476 -> 130643 bytes .../www_static/home-assistant-polymer | 2 +- .../panels/ha-panel-dev-service.html | 2 +- .../panels/ha-panel-dev-service.html.gz | Bin 17702 -> 17764 bytes .../www_static/panels/ha-panel-map.html | 184 +++++++++++++++++- .../www_static/panels/ha-panel-map.html.gz | Bin 42075 -> 43807 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2326 -> 2323 bytes .../www_static/webcomponents-lite.min.js | 6 +- .../www_static/webcomponents-lite.min.js.gz | Bin 12355 -> 12360 bytes 12 files changed, 191 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 14650b47cb7..e6211c145e2 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -2,17 +2,17 @@ FINGERPRINTS = { "core.js": "5dfb2d3e567fad37af0321d4b29265ed", - "frontend.html": "d4f164e559944b8abc560d7b46131714", + "frontend.html": "ac15b11435132aab3da592f9e7b05400", "mdi.html": "46a76f877ac9848899b8ed382427c16f", "micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a", "panels/ha-panel-dev-event.html": "c2d5ec676be98d4474d19f94d0262c1e", "panels/ha-panel-dev-info.html": "a9c07bf281fe9791fb15827ec1286825", - "panels/ha-panel-dev-service.html": "b3fe49532c5c03198fafb0c6ed58b76a", + "panels/ha-panel-dev-service.html": "20420e2387fd93db53c8d778097e3d59", "panels/ha-panel-dev-state.html": "65e5f791cc467561719bf591f1386054", "panels/ha-panel-dev-template.html": "7d744ab7f7c08b6d6ad42069989de400", "panels/ha-panel-history.html": "efe1bcdd7733b09e55f4f965d171c295", "panels/ha-panel-iframe.html": "d920f0aa3c903680f2f8795e2255daab", "panels/ha-panel-logbook.html": "4bc5c8370a85a4215413fbae8f85addb", - "panels/ha-panel-map.html": "1bf6965b24d76db71a1871865cd4a3a2", + "panels/ha-panel-map.html": "3b0ca63286cbe80f27bd36dbc2434e89", "websocket_test.html": "575de64b431fe11c3785bf96d7813450" } diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index 54b9cc4d5e4..dd0eba180ec 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -1,5 +1,5 @@

\ No newline at end of file +},customStyle:null,getComputedStyleValue:function(e){return!i&&this._styleProperties&&this._styleProperties[e]||getComputedStyle(this).getPropertyValue(e)},_setupStyleProperties:function(){this.customStyle={},this._styleCache=null,this._styleProperties=null,this._scopeSelector=null,this._ownStyleProperties=null,this._customStyle=null},_needsStyleProperties:function(){return Boolean(!i&&this._ownStylePropertyNames&&this._ownStylePropertyNames.length)},_validateApplyShim:function(){if(this.__applyShimInvalid){Polymer.ApplyShim.transform(this._styles,this.__proto__);var e=n.elementStyles(this);if(s){var t=this._template.content.querySelector("style");t&&(t.textContent=e)}else{var r=this._scopeStyle&&this._scopeStyle.nextSibling;r&&(r.textContent=e)}}},_beforeAttached:function(){this._scopeSelector&&!this.__stylePropertiesInvalid||!this._needsStyleProperties()||(this.__stylePropertiesInvalid=!1,this._updateStyleProperties())},_findStyleHost:function(){for(var e,t=this;e=Polymer.dom(t).getOwnerRoot();){if(Polymer.isInstance(e.host))return e.host;t=e.host}return r},_updateStyleProperties:function(){var e,n=this._findStyleHost();n._styleProperties||n._computeStyleProperties(),n._styleCache||(n._styleCache=new Polymer.StyleCache);var r=t.propertyDataFromStyles(n._styles,this),i=!this.__notStyleScopeCacheable;i&&(r.key.customStyle=this.customStyle,e=n._styleCache.retrieve(this.is,r.key,this._styles));var a=Boolean(e);a?this._styleProperties=e._styleProperties:this._computeStyleProperties(r.properties),this._computeOwnStyleProperties(),a||(e=o.retrieve(this.is,this._ownStyleProperties,this._styles));var l=Boolean(e)&&!a,c=this._applyStyleProperties(e);a||(c=c&&s?c.cloneNode(!0):c,e={style:c,_scopeSelector:this._scopeSelector,_styleProperties:this._styleProperties},i&&(r.key.customStyle={},this.mixin(r.key.customStyle,this.customStyle),n._styleCache.store(this.is,e,r.key,this._styles)),l||o.store(this.is,Object.create(e),this._ownStyleProperties,this._styles))},_computeStyleProperties:function(e){var n=this._findStyleHost();n._styleProperties||n._computeStyleProperties();var r=Object.create(n._styleProperties),s=t.hostAndRootPropertiesForScope(this);this.mixin(r,s.hostProps),e=e||t.propertyDataFromStyles(n._styles,this).properties,this.mixin(r,e),this.mixin(r,s.rootProps),t.mixinCustomStyle(r,this.customStyle),t.reify(r),this._styleProperties=r},_computeOwnStyleProperties:function(){for(var e,t={},n=0;n0&&l.push(t);return[{removed:a,added:l}]}},Polymer.Collection.get=function(e){return Polymer._collections.get(e)||new Polymer.Collection(e)},Polymer.Collection.applySplices=function(e,t){var n=Polymer._collections.get(e);return n?n._applySplices(t):null},Polymer({is:"dom-repeat",extends:"template",_template:null,properties:{items:{type:Array},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},sort:{type:Function,observer:"_sortChanged"},filter:{type:Function,observer:"_filterChanged"},observe:{type:String,observer:"_observeChanged"},delay:Number,renderedItemCount:{type:Number,notify:!0,readOnly:!0},initialCount:{type:Number,observer:"_initializeChunking"},targetFramerate:{type:Number,value:20},_targetFrameTime:{type:Number,computed:"_computeFrameTime(targetFramerate)"}},behaviors:[Polymer.Templatizer],observers:["_itemsChanged(items.*)"],created:function(){this._instances=[],this._pool=[],this._limit=1/0;var e=this;this._boundRenderChunk=function(){e._renderChunk()}},detached:function(){this.__isDetached=!0;for(var e=0;e=0;t--){var n=this._instances[t];n.isPlaceholder&&t=this._limit&&(n=this._downgradeInstance(t,n.__key__)),e[n.__key__]=t,n.isPlaceholder||n.__setProperty(this.indexAs,t,!0)}this._pool.length=0,this._setRenderedItemCount(this._instances.length),this.fire("dom-change"),this._tryRenderChunk()},_applyFullRefresh:function(){var e,t=this.collection;if(this._sortFn)e=t?t.getKeys():[];else{e=[];var n=this.items;if(n)for(var r=0;r=r;a--)this._detachAndRemoveInstance(a)},_numericSort:function(e,t){return e-t},_applySplicesUserSort:function(e){for(var t,n,r=this.collection,s={},i=0;i=0;i--){var c=a[i];void 0!==c&&this._detachAndRemoveInstance(c)}var h=this;if(l.length){this._filterFn&&(l=l.filter(function(e){return h._filterFn(r.getItem(e))})),l.sort(function(e,t){return h._sortFn(r.getItem(e),r.getItem(t))});var u=0;for(i=0;i>1,a=this._instances[o].__key__,l=this._sortFn(n.getItem(a),r);if(l<0)e=o+1;else{if(!(l>0)){i=o;break}s=o-1}}return i<0&&(i=s+1),this._insertPlaceholder(i,t),i},_applySplicesArrayOrder:function(e){for(var t,n=0;n=0?(e=this.as+"."+e.substring(n+1),i._notifyPath(e,t,!0)):i.__setProperty(this.as,t,!0))}},itemForElement:function(e){var t=this.modelForElement(e);return t&&t[this.as]},keyForElement:function(e){var t=this.modelForElement(e);return t&&t.__key__},indexForElement:function(e){var t=this.modelForElement(e);return t&&t[this.indexAs]}}),Polymer({is:"array-selector",_template:null,properties:{items:{type:Array,observer:"clearSelection"},multi:{type:Boolean,value:!1,observer:"clearSelection"},selected:{type:Object,notify:!0},selectedItem:{type:Object,notify:!0},toggle:{type:Boolean,value:!1}},clearSelection:function(){if(Array.isArray(this.selected))for(var e=0;e \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/frontend.html.gz b/homeassistant/components/frontend/www_static/frontend.html.gz index 3bf5bab1b5944da1c6375064d0b6d982ab667b5d..b1488e61a11ee39c694803a710a4e6b8eea2e090 100644 GIT binary patch delta 101571 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 Du3c!6 delta 101406 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�WS=#HPIF-l*j9%A-Sy$Jx1|LGCy#pgr4+> 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 diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 4697af1b0d9..336e974fe6f 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 4697af1b0d96e7a21454539888c68189668fa80d +Subproject commit 336e974fe6f4196aaf0b309e805a009ef0fdfd66 diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html index 51805ebd91d..e4fd1211753 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html @@ -1 +1 @@ -

\ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html.gz index f6c74234e4d56e43ca9be97211a2b65756a5e07c..2419c25adbd0c227748e2991b75bdd3295e45bd4 100644 GIT binary patch delta 12168 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 delta 12105 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 diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html index d63acba7549..38dd2b6e961 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html @@ -1,4 +1,180 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html.gz index e153a5290fbbb505b414fb4b8b7b05b3455437f5..56a98ed3431887e2fdb5c9f724ac501f8244834b 100644 GIT binary patch literal 43807 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 literal 42075 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 diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index b125336669c..d2ef4b42439 100644 --- a/homeassistant/components/frontend/www_static/service_worker.js +++ b/homeassistant/components/frontend/www_static/service_worker.js @@ -1 +1 @@ -"use strict";function setOfCachedUrls(e){return e.keys().then(function(e){return e.map(function(e){return e.url})}).then(function(e){return new Set(e)})}function notificationEventCallback(e,t){firePushCallback({action:t.action,data:t.notification.data,tag:t.notification.tag,type:e},t.notification.data.jwt)}function firePushCallback(e,t){delete e.data.jwt,0===Object.keys(e.data).length&&e.data.constructor===Object&&delete e.data,fetch("/api/notify.html5/callback",{method:"POST",headers:new Headers({"Content-Type":"application/json",Authorization:"Bearer "+t}),body:JSON.stringify(e)})}var precacheConfig=[["/","e14330e71c13caf3a8ad2ec699e46047"],["/frontend/panels/dev-event-c2d5ec676be98d4474d19f94d0262c1e.html","6c55fc819751923ab00c62ae3fbb7222"],["/frontend/panels/dev-info-a9c07bf281fe9791fb15827ec1286825.html","931f9327e368db710fcdf5f7202f2588"],["/frontend/panels/dev-service-b3fe49532c5c03198fafb0c6ed58b76a.html","4194cb43b74108dc6d10354da2fd81fd"],["/frontend/panels/dev-state-65e5f791cc467561719bf591f1386054.html","78158786a6597ef86c3fd6f4985cde92"],["/frontend/panels/dev-template-7d744ab7f7c08b6d6ad42069989de400.html","8a6ee994b1cdb45b081299b8609915ed"],["/frontend/panels/map-1bf6965b24d76db71a1871865cd4a3a2.html","a74c01c2ee68c83c9938af067ec33b81"],["/static/core-5dfb2d3e567fad37af0321d4b29265ed.js","9a50270db7613e3af449f6c773366f4d"],["/static/frontend-d4f164e559944b8abc560d7b46131714.html","fd803353b0ff1844aa4677b8a0f79fea"],["/static/mdi-46a76f877ac9848899b8ed382427c16f.html","a846c4082dd5cffd88ac72cbe943e691"],["static/fonts/roboto/Roboto-Bold.ttf","d329cc8b34667f114a95422aaad1b063"],["static/fonts/roboto/Roboto-Light.ttf","7b5fb88f12bec8143f00e21bc3222124"],["static/fonts/roboto/Roboto-Medium.ttf","fe13e4170719c2fc586501e777bde143"],["static/fonts/roboto/Roboto-Regular.ttf","ac3f799d5bbaf5196fab15ab8de8431c"],["static/icons/favicon-192x192.png","419903b8422586a7e28021bbe9011175"],["static/icons/favicon.ico","04235bda7843ec2fceb1cbe2bc696cf4"],["static/images/card_media_player_bg.png","a34281d1c1835d338a642e90930e61aa"],["static/webcomponents-lite.min.js","b0f32ad3c7749c40d486603f31c9d8b1"]],cacheName="sw-precache-v2--"+(self.registration?self.registration.scope:""),ignoreUrlParametersMatching=[/^utm_/],addDirectoryIndex=function(e,t){var n=new URL(e);return"/"===n.pathname.slice(-1)&&(n.pathname+=t),n.toString()},createCacheKey=function(e,t,n,a){var c=new URL(e);return a&&c.toString().match(a)||(c.search+=(c.search?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(n)),c.toString()},isPathWhitelisted=function(e,t){if(0===e.length)return!0;var n=new URL(t).pathname;return e.some(function(e){return n.match(e)})},stripIgnoredUrlParameters=function(e,t){var n=new URL(e);return n.search=n.search.slice(1).split("&").map(function(e){return e.split("=")}).filter(function(e){return t.every(function(t){return!t.test(e[0])})}).map(function(e){return e.join("=")}).join("&"),n.toString()},hashParamName="_sw-precache",urlsToCacheKeys=new Map(precacheConfig.map(function(e){var t=e[0],n=e[1],a=new URL(t,self.location),c=createCacheKey(a,hashParamName,n,!1);return[a.toString(),c]}));self.addEventListener("install",function(e){e.waitUntil(caches.open(cacheName).then(function(e){return setOfCachedUrls(e).then(function(t){return Promise.all(Array.from(urlsToCacheKeys.values()).map(function(n){if(!t.has(n))return e.add(new Request(n,{credentials:"same-origin"}))}))})}).then(function(){return self.skipWaiting()}))}),self.addEventListener("activate",function(e){var t=new Set(urlsToCacheKeys.values());e.waitUntil(caches.open(cacheName).then(function(e){return e.keys().then(function(n){return Promise.all(n.map(function(n){if(!t.has(n.url))return e.delete(n)}))})}).then(function(){return self.clients.claim()}))}),self.addEventListener("fetch",function(e){if("GET"===e.request.method){var t,n=stripIgnoredUrlParameters(e.request.url,ignoreUrlParametersMatching);t=urlsToCacheKeys.has(n);var a="index.html";!t&&a&&(n=addDirectoryIndex(n,a),t=urlsToCacheKeys.has(n));var c="/";!t&&c&&"navigate"===e.request.mode&&isPathWhitelisted(["^((?!(static|api|local|service_worker.js|manifest.json)).)*$"],e.request.url)&&(n=new URL(c,self.location).toString(),t=urlsToCacheKeys.has(n)),t&&e.respondWith(caches.open(cacheName).then(function(e){return e.match(urlsToCacheKeys.get(n)).then(function(e){if(e)return e;throw Error("The cached response that was expected is missing.")})}).catch(function(t){return console.warn('Couldn\'t serve response for "%s" from cache: %O',e.request.url,t),fetch(e.request)}))}}),self.addEventListener("push",function(e){var t;e.data&&(t=e.data.json(),e.waitUntil(self.registration.showNotification(t.title,t).then(function(e){firePushCallback({type:"received",tag:t.tag,data:t.data},t.data.jwt)})))}),self.addEventListener("notificationclick",function(e){var t;notificationEventCallback("clicked",e),e.notification.close(),e.notification.data&&e.notification.data.url&&(t=e.notification.data.url,t&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var n,a;for(n=0;nstP3wArnM37nKG@r^ z;LGDLR!w>9-Jbrmg6qM1Ft~!-wzgEYDRd#Z{m=6&sLV57mV(Q#F8Id#u8RiVuG;x_ z^*isrJ2yf9;45x8{%==KVAp)ZXZP1}$u~DkIEP#R$S1*Y$F z;dDBEBffxtG(CF#D=#Ranwj}$D=%3y1&a=8Qh~?-5I_sP}e7P*wj*h>y zb>;X^S16<@{@bmcJHG;Npcy!4=GOB?t!~c$`Tos+>%eACHA5@1jPhrRx!A zGR%a3ra95TGDfr@Nlr76gyv~ZlZ_e{5zQie5v92j840yiI?)*osisMupH|aCb5%$f z(J-bV&?wKeVv!O_By*KzdB{+xO4wEt(?l`|nGR_f3Wa*JI97^Aie;(d4`?#nz$i@s z?P5gAIL(rjWP}Nwpl2k?(=drQda@in&GM9grwLl1^HfG!r8;JLA{DR)fHSaImR41U z@r=31bSA@Gq$=eKeM}k4nSwYBH>z@;0x%W}B9({}5$1$4CeR$lNCN7(Dr_sGNQ9E7 z5ynCa$U{vtp`ug?N#iJnd<&YQ6aa{fq8zsZ3rU_J0xC+Rh@*`L3s51)vTk6MC@rXe ziXcfd%~h0f9b%HISWre0LKS>zZ7_He(k#S?rzC=i>o{gQm01==DPpxRcjLf_OOgme z;wT{z)OVv1gIMMRiJKNIz`n9a>vRwfcH@>~-t082KGbchu} zgp9CI35|ay>lLVCwO9+&fDwsF7Gi=+s%4U=Nk|~eFhu}m|4i6Bn5|0Qtfg^(%>Ilq zl?cH#c9K+c>;zoo3i3E2a#vbm`}SD#EBi3QuJaB52Fq%Oa$>?*7>OJqLW6h)G!M~3 zVN;TjEIBDBz<+GpjA@i$B4nr)tXqIZBY+B-vQ+9lh>8WDL5oDtsLKUH!!NNcZ=ksp zv$Zumim|gPB1s-43X201jG`%jED8Y|GvAeV4MNt7WnE$SZAWEckl2f=FM}N0U!s)M>9r8&Viu(b32`b6Y5N(7>!f0_hm$$-zp{ z${LB-aXi16Ram1qiM-_vN;F7euQ>7`QqS~a{QJr*F2|pJuGDWx$d*2TZ(dXizD@6D z49m-woT{m%!H@4=B417Vu>csJJSZ+Vmo8)RcG+v>${qgF+01KU&S_AzGe+ZVvUF7_($jZ7O^e{iB z`zh@5eVZ_gACV3E7ktNfUw*#zyh$ey>#m#2U)rRq5L2hXITpuJ$KSOKf@@xwkCiD( zxAUM4u)ZsI+bB+d9}EtUBlos$BQ$v1)Qh5p0M)xsn}**6NW%;F9-6@wFIRxan0pbd zx+=ghBMi2Jw&6q{T?^wo_|M8_K;?f&=oETg@UlI3TC{(J$HZwJo)OoMy= z2vD*tEC=B)FBU(6syiO-eP*#z155h-Cf zJm~uFh4Z@`>ppqp_C)^!Pm(`uODKP=k0zJbb@LS(r1~F|jt3ooq({E7N8kopq%QTT zF!Mj3r#;Kump_A!2M@o)oPcdMPRzWiuLsYYrp65VFo!{>QVn{GS{Rr)H-l^54&d7o z1BI`Oc7TcBqGN&6XRz!nIMR{qR9Ba_3Y*G({H$J;s`~e1Gq7mGoeo{&>H3$}8Q6Z+ zTW~)3<;~-Lw2>Wu*H-}B<*p!3SHyDF&W|*XNq?V!!9%uK-&C}=^!(j^abzf)*VnIi zu0>p=#KM%8whv)GyqoFnRvgTBD6a4rw!VU~w=U~j8vA3fUhZyNyoc(2_l5@hguVVa zboKNNlGA--4FT);-hGcO>lWODvzjC4SIGHRAvOb4>F8RnTI@XozR7qVbZf3R r!7nyu*joG4sorcmeB=JPa3FsB;dn3*xVwwPtvC4}25Xogl@tH~>2Y$H delta 2324 zcmV+v3G4Qg5|$EwABzYGH%~@b0t0hpa&~EBWnXu1a%*LBE^2cCrC9rOo5~gbR}`jK zff^we7FeumGP${#Hf>&$$K(e$*Rzka5(xqoR(4$5|9j7ZBukd%+&i5~A_BYT@twza zcAZrVgVr>KG|oh?Drt(k8nj^E=@(qiL49t@)&=jn0kdjAL-5e&Y;Wm{XS+7!Bw-2Ug~1ytq*FH6DYcNcu)UF)KO_p5fk zeS6KjeWxbqAAH3P$N%lh3G6%H@Y((M_{uj|OE`sF|A8&Rw@b5Q+JWxQA_XNFKz}zo z{BSy*z7yYnK$;%C{*xD!P|eJII9xB4b%l{wNmDo54a4D{IA4R2bJrR3Wijr|y9(xJ zQ6^)#w!!hQ7hvYKI(6Q^`}oQ6=fD*-?WslgAN{j??YyWfgIJC}p|j4Z!>IdmGrysb*+JAG8bJ43-T@n>naK z7qjWvnKO2L2MCSh5Hcc3EV+(3<0=A~<~h(bq?z;8$A!A-%u?eeub^zl3NA)qV?L6R zN^p6W3dotFG^2{-I;Sd((nu2MP(VGYOcE^_$+LvyQOrdc$~58-Yay~IijM0kDqW9w zF2hWJ=!g*wd6p9`NW!8FB#BtcqGY2ckBQD>{1B&1iHw9=DxK&o3L_mQj2&0gLUU0_ z7>QT|&67Bii40?sGtIR?TR|mEWGUZhq9mtM&{$-YgiOg)kuXlE;*nNprFuk@;RZ%& z0%%uGq@-z~J<+(s}@|+}a#3gJiBO-K~ zr-_KD%2JCvCoCf@MH4BHd9=~MGb%$OBY>1i7Rx-38P{QofsA9pNUy;HRLHTc8yF>j zN{dLvkffRBD$a0q91%rDlt&1m3cj^A>^uphEJV#Ii6Q2i(p;x9%i=gitkj;|jRPY^ zHAyKX3HnS0<3c8Bs4_uO2*zU@0t{#v$4M+gtqDUYIfg954Iu_l1K*RrP{oL*JWDmp zGA?sQ8M7dQidjUXOp;V@;b1hCG-Q!~Qi;^4hH;ri5=)83kmfxc8>`XicHGpWHud;J z_cQvnE>&QRMo}t`aw(aJX^Kb@LV2FhDB_$eBEmHOnW)#rY;M-FGLdM(m?n_`ELj@s zFocK*8DpW6i2h908&Jh+u@$3Ht!ERmq!wwKR^| zpXIqqgy0%GNvb(^0xp;WMq?s(r4_bsk2Sxr4wVRR9VM$U=bLaBoWW(5*R$1u+h z-UO|zk%%3~^NU%9HHwqSd)}Z#gB13LBM&0=OwY!@ugv0n{MF}5{f2~pZ0YmrRi)s^ z^lrwmylly-npztC{NXk7)ubOgke-ljt6<5^yh7cu87uJKNPoT>BBm&)^exo2+CzDHla%rTTDq73RDK81GepaSc$#OsZH z5>EDkGu{@H$#%4B>jgYG(ye{#rUTzj3(HqsFx6f(|5&6@T93$d^RSK;@q!lT7vmyQ z-tqZ!y=LmzAygM7YJO;;32@|SuI@gW&8H{WxuC@X^(_4Ab))QmQC;8aqS~nHpV72? z`7`J3yu+X`lk=TAaeN$>+fVf-x!MkmH>hoYygD$zLT9GdK)=Etf@N_RIln8ivhD{x z%#Z1Q3cGyYCd}d|WP|=0-!a~oUvE8c(#gZR>*n&;HmNGa)G2U|#c|Z}cP)e9k{9N4 zWs1`6JZJ-~@5>u_K$E}o)wjYz;u5OPC7gO zAZ+dTV)+FT>65{3@Q=W0&oLJmrhPp7NN>(eM;)B}AGjZXIqX#rqFp@(r9J!Yz}cT^ zaLpe9N|uG?ApGUU;wMmb$D@6m&lXv3WjUE}Hcm)05B ze$`uWI{4+?(|xp&9e>wX0NdAHK^(7$<*J=O&^RXjeF6p#*MvwAA9w3ciZAUR`0tvG}tHX z^~a&B$8V6FZjUtttmAw4J+iD@a1UPhs6Ft~hGz}ugWvir-)-r|>$cXV?sIIQYj7^H zP1KjpL-%CeT;%f!<_gwaIH~@&8P+D%$%%(q&5`pf32&&127>t&&-1==[34,35,60,62,63,96].indexOf(t)?e:encodeURIComponent(e)}function i(e){var t=e.charCodeAt(0);return t>32&&127>t&&-1==[34,35,60,62,96].indexOf(t)?e:encodeURIComponent(e)}function a(e,a,s){function c(e){g.push(e)}var d=a||"scheme start",l=0,u="",w=!1,_=!1,g=[];e:for(;(e[l-1]!=p||0==l)&&!this._isInvalid;){var b=e[l];switch(d){case"scheme start":if(!b||!m.test(b)){if(a){c("Invalid scheme.");break e}u="",d="no scheme";continue}u+=b.toLowerCase(),d="scheme";break;case"scheme":if(b&&v.test(b))u+=b.toLowerCase();else{if(":"!=b){if(a){if(p==b)break e;c("Code point not allowed in scheme: "+b);break e}u="",l=0,d="no scheme";continue}if(this._scheme=u,u="",a)break e;t(this._scheme)&&(this._isRelative=!0),d="file"==this._scheme?"relative":this._isRelative&&s&&s._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==b?(this._query="?",d="query"):"#"==b?(this._fragment="#",d="fragment"):p!=b&&" "!=b&&"\n"!=b&&"\r"!=b&&(this._schemeData+=r(b));break;case"no scheme":if(s&&t(s._scheme)){d="relative";continue}c("Missing scheme."),n.call(this);break;case"relative or authority":if("/"!=b||"/"!=e[l+1]){c("Expected /, got: "+b),d="relative";continue}d="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=s._scheme),p==b){this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._username=s._username,this._password=s._password;break e}if("/"==b||"\\"==b)"\\"==b&&c("\\ is an invalid code point."),d="relative slash";else if("?"==b)this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query="?",this._username=s._username,this._password=s._password,d="query";else{if("#"!=b){var y=e[l+1],E=e[l+2];("file"!=this._scheme||!m.test(b)||":"!=y&&"|"!=y||p!=E&&"/"!=E&&"\\"!=E&&"?"!=E&&"#"!=E)&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password,this._path=s._path.slice(),this._path.pop()),d="relative path";continue}this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._fragment="#",this._username=s._username,this._password=s._password,d="fragment"}break;case"relative slash":if("/"!=b&&"\\"!=b){"file"!=this._scheme&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password),d="relative path";continue}"\\"==b&&c("\\ is an invalid code point."),d="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=b){c("Expected '/', got: "+b),d="authority ignore slashes";continue}d="authority second slash";break;case"authority second slash":if(d="authority ignore slashes","/"!=b){c("Expected '/', got: "+b);continue}break;case"authority ignore slashes":if("/"!=b&&"\\"!=b){d="authority";continue}c("Expected authority, got: "+b);break;case"authority":if("@"==b){w&&(c("@ already seen."),u+="%40"),w=!0;for(var L=0;L>>0)+(t++ +"__")};n.prototype={set:function(t,n){var o=t[this.name];return o&&o[0]===t?o[1]=n:e(t,this.name,{value:[t,n],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0},"delete":function(e){var t=e[this.name];return t&&t[0]===e?(t[0]=t[1]=void 0,!0):!1},has:function(e){var t=e[this.name];return t?t[0]===e:!1}},window.WeakMap=n}(),function(e){function t(e){b.push(e),g||(g=!0,m(o))}function n(e){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(e)||e}function o(){g=!1;var e=b;b=[],e.sort(function(e,t){return e.uid_-t.uid_});var t=!1;e.forEach(function(e){var n=e.takeRecords();r(e),n.length&&(e.callback_(n,e),t=!0)}),t&&o()}function r(e){e.nodes_.forEach(function(t){var n=v.get(t);n&&n.forEach(function(t){t.observer===e&&t.removeTransientObservers()})})}function i(e,t){for(var n=e;n;n=n.parentNode){var o=v.get(n);if(o)for(var r=0;r0){var r=n[o-1],i=f(r,e);if(i)return void(n[o-1]=i)}else t(this.observer);n[o]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=v.get(e);t||v.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=v.get(e),n=0;n":return">";case" ":return" "}}function t(t){return t.replace(u,e)}var n="undefined"==typeof HTMLTemplateElement;/Trident/.test(navigator.userAgent)&&!function(){var e=document.importNode;document.importNode=function(){var t=e.apply(document,arguments);if(t.nodeType===Node.DOCUMENT_FRAGMENT_NODE){var n=document.createDocumentFragment();return n.appendChild(t),n}return t}}();var o=function(){if(!n){var e=document.createElement("template"),t=document.createElement("template");t.content.appendChild(document.createElement("div")),e.content.appendChild(t);var o=e.cloneNode(!0);return 0===o.content.childNodes.length||0===o.content.firstChild.content.childNodes.length}}(),r="template",i=function(){};if(n){var a=document.implementation.createHTMLDocument("template"),s=!0,c=document.createElement("style");c.textContent=r+"{display:none;}";var d=document.head;d.insertBefore(c,d.firstElementChild),i.prototype=Object.create(HTMLElement.prototype),i.decorate=function(e){if(!e.content){e.content=a.createDocumentFragment();for(var n;n=e.firstChild;)e.content.appendChild(n);if(e.cloneNode=function(e){return i.cloneNode(this,e)},s)try{Object.defineProperty(e,"innerHTML",{get:function(){for(var e="",n=this.content.firstChild;n;n=n.nextSibling)e+=n.outerHTML||t(n.data);return e},set:function(e){for(a.body.innerHTML=e,i.bootstrap(a);this.content.firstChild;)this.content.removeChild(this.content.firstChild);for(;a.body.firstChild;)this.content.appendChild(a.body.firstChild)},configurable:!0})}catch(o){s=!1}i.bootstrap(e.content)}},i.bootstrap=function(e){for(var t,n=e.querySelectorAll(r),o=0,a=n.length;a>o&&(t=n[o]);o++)i.decorate(t)},document.addEventListener("DOMContentLoaded",function(){i.bootstrap(document)});var l=document.createElement;document.createElement=function(){"use strict";var e=l.apply(document,arguments);return"template"===e.localName&&i.decorate(e),e};var u=/[&\u00A0<>]/g}if(n||o){var h=Node.prototype.cloneNode;i.cloneNode=function(e,t){var n=h.call(e,!1);return this.decorate&&this.decorate(n),t&&(n.content.appendChild(h.call(e.content,!0)),this.fixClonedDom(n.content,e.content)),n},i.fixClonedDom=function(e,t){if(t.querySelectorAll)for(var n,o,i=t.querySelectorAll(r),a=e.querySelectorAll(r),s=0,c=a.length;c>s;s++)o=i[s],n=a[s],this.decorate&&this.decorate(o),n.parentNode.replaceChild(o.cloneNode(!0),n)};var f=document.importNode;Node.prototype.cloneNode=function(e){var t=h.call(this,e);return e&&i.fixClonedDom(t,this),t},document.importNode=function(e,t){if(e.localName===r)return i.cloneNode(e,t);var n=f.call(document,e,t);return t&&i.fixClonedDom(n,e),n},o&&(HTMLTemplateElement.prototype.cloneNode=function(e){return i.cloneNode(this,e)})}n&&(window.HTMLTemplateElement=i)}(),function(e){"use strict";if(!window.performance){var t=Date.now();window.performance={now:function(){return Date.now()-t}}}window.requestAnimationFrame||(window.requestAnimationFrame=function(){var e=window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;return e?function(t){return e(function(){t(performance.now())})}:function(e){return window.setTimeout(e,1e3/60)}}()),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(){return window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||function(e){clearTimeout(e)}}());var n=function(){var e=document.createEvent("Event");return e.initEvent("foo",!0,!0),e.preventDefault(),e.defaultPrevented}();if(!n){var o=Event.prototype.preventDefault;Event.prototype.preventDefault=function(){this.cancelable&&(o.call(this),Object.defineProperty(this,"defaultPrevented",{get:function(){return!0},configurable:!0}))}}var r=/Trident/.test(navigator.userAgent);if((!window.CustomEvent||r&&"function"!=typeof window.CustomEvent)&&(window.CustomEvent=function(e,t){t=t||{};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,Boolean(t.bubbles),Boolean(t.cancelable),t.detail),n},window.CustomEvent.prototype=window.Event.prototype),!window.Event||r&&"function"!=typeof window.Event){var i=window.Event;window.Event=function(e,t){t=t||{};var n=document.createEvent("Event");return n.initEvent(e,Boolean(t.bubbles),Boolean(t.cancelable)),n},window.Event.prototype=i.prototype}}(window.WebComponents),window.HTMLImports=window.HTMLImports||{flags:{}},function(e){function t(e,t){t=t||p,o(function(){i(e,t)},t)}function n(e){return"complete"===e.readyState||e.readyState===w}function o(e,t){if(n(t))e&&e();else{var r=function(){"complete"!==t.readyState&&t.readyState!==w||(t.removeEventListener(_,r),o(e,t))};t.addEventListener(_,r)}}function r(e){e.target.__loaded=!0}function i(e,t){function n(){c==d&&e&&e({allImports:s,loadedImports:l,errorImports:u})}function o(e){r(e),l.push(this),c++,n()}function i(e){u.push(this),c++,n()}var s=t.querySelectorAll("link[rel=import]"),c=0,d=s.length,l=[],u=[];if(d)for(var h,f=0;d>f&&(h=s[f]);f++)a(h)?(l.push(this),c++,n()):(h.addEventListener("load",o),h.addEventListener("error",i));else n()}function a(e){return u?e.__loaded||e["import"]&&"loading"!==e["import"].readyState:e.__importParsed}function s(e){for(var t,n=0,o=e.length;o>n&&(t=e[n]);n++)c(t)&&d(t)}function c(e){return"link"===e.localName&&"import"===e.rel}function d(e){var t=e["import"];t?r({target:e}):(e.addEventListener("load",r),e.addEventListener("error",r))}var l="import",u=Boolean(l in document.createElement("link")),h=Boolean(window.ShadowDOMPolyfill),f=function(e){return h?window.ShadowDOMPolyfill.wrapIfNeeded(e):e},p=f(document),m={get:function(){var e=window.HTMLImports.currentScript||document.currentScript||("complete"!==document.readyState?document.scripts[document.scripts.length-1]:null);return f(e)},configurable:!0};Object.defineProperty(document,"_currentScript",m),Object.defineProperty(p,"_currentScript",m);var v=/Trident/.test(navigator.userAgent),w=v?"complete":"interactive",_="readystatechange";u&&(new MutationObserver(function(e){for(var t,n=0,o=e.length;o>n&&(t=e[n]);n++)t.addedNodes&&s(t.addedNodes)}).observe(document.head,{childList:!0}),function(){if("loading"===document.readyState)for(var e,t=document.querySelectorAll("link[rel=import]"),n=0,o=t.length;o>n&&(e=t[n]);n++)d(e)}()),t(function(e){window.HTMLImports.ready=!0,window.HTMLImports.readyTime=(new Date).getTime();var t=p.createEvent("CustomEvent");t.initCustomEvent("HTMLImportsLoaded",!0,!0,e),p.dispatchEvent(t)}),e.IMPORT_LINK_TYPE=l,e.useNative=u,e.rootDocument=p,e.whenReady=t,e.isIE=v}(window.HTMLImports),function(e){var t=[],n=function(e){t.push(e)},o=function(){t.forEach(function(t){t(e)})};e.addModule=n,e.initializeModules=o}(window.HTMLImports),window.HTMLImports.addModule(function(e){var t=/(url\()([^)]*)(\))/g,n=/(@import[\s]+(?!url\())([^;]*)(;)/g,o={resolveUrlsInStyle:function(e,t){var n=e.ownerDocument,o=n.createElement("a");return e.textContent=this.resolveUrlsInCssText(e.textContent,t,o),e},resolveUrlsInCssText:function(e,o,r){var i=this.replaceUrls(e,r,o,t);return i=this.replaceUrls(i,r,o,n)},replaceUrls:function(e,t,n,o){return e.replace(o,function(e,o,r,i){var a=r.replace(/["']/g,"");return n&&(a=new URL(a,n).href),t.href=a,a=t.href,o+"'"+a+"'"+i})}};e.path=o}),window.HTMLImports.addModule(function(e){var t={async:!0,ok:function(e){return e.status>=200&&e.status<300||304===e.status||0===e.status},load:function(n,o,r){var i=new XMLHttpRequest;return(e.flags.debug||e.flags.bust)&&(n+="?"+Math.random()),i.open("GET",n,t.async),i.addEventListener("readystatechange",function(e){if(4===i.readyState){var n=null;try{var a=i.getResponseHeader("Location");a&&(n="/"===a.substr(0,1)?location.origin+a:a)}catch(e){console.error(e.message)}o.call(r,!t.ok(i)&&i,i.response||i.responseText,n)}}),i.send(),i},loadDocument:function(e,t,n){this.load(e,t,n).responseType="document"}};e.xhr=t}),window.HTMLImports.addModule(function(e){var t=e.xhr,n=e.flags,o=function(e,t){this.cache={},this.onload=e,this.oncomplete=t,this.inflight=0,this.pending={}};o.prototype={addNodes:function(e){this.inflight+=e.length;for(var t,n=0,o=e.length;o>n&&(t=e[n]);n++)this.require(t);this.checkDone()},addNode:function(e){this.inflight++,this.require(e),this.checkDone()},require:function(e){var t=e.src||e.href;e.__nodeUrl=t,this.dedupe(t,e)||this.fetch(t,e)},dedupe:function(e,t){if(this.pending[e])return this.pending[e].push(t),!0;return this.cache[e]?(this.onload(e,t,this.cache[e]),this.tail(),!0):(this.pending[e]=[t],!1)},fetch:function(e,o){if(n.load&&console.log("fetch",e,o),e)if(e.match(/^data:/)){var r=e.split(","),i=r[0],a=r[1];a=i.indexOf(";base64")>-1?atob(a):decodeURIComponent(a),setTimeout(function(){this.receive(e,o,null,a)}.bind(this),0)}else{var s=function(t,n,r){this.receive(e,o,t,n,r)}.bind(this);t.load(e,s)}else setTimeout(function(){this.receive(e,o,{error:"href must be specified"},null)}.bind(this),0)},receive:function(e,t,n,o,r){this.cache[e]=o;for(var i,a=this.pending[e],s=0,c=a.length;c>s&&(i=a[s]);s++)this.onload(e,i,o,n,r),this.tail();this.pending[e]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}},e.Loader=o}),window.HTMLImports.addModule(function(e){var t=function(e){this.addCallback=e,this.mo=new MutationObserver(this.handler.bind(this))};t.prototype={handler:function(e){for(var t,n=0,o=e.length;o>n&&(t=e[n]);n++)"childList"===t.type&&t.addedNodes.length&&this.addedNodes(t.addedNodes)},addedNodes:function(e){this.addCallback&&this.addCallback(e);for(var t,n=0,o=e.length;o>n&&(t=e[n]);n++)t.children&&t.children.length&&this.addedNodes(t.children)},observe:function(e){this.mo.observe(e,{childList:!0,subtree:!0})}},e.Observer=t}),window.HTMLImports.addModule(function(e){function t(e){return"link"===e.localName&&e.rel===l}function n(e){var t=o(e);return"data:text/javascript;charset=utf-8,"+encodeURIComponent(t)}function o(e){return e.textContent+r(e)}function r(e){var t=e.ownerDocument;t.__importedScripts=t.__importedScripts||0;var n=e.ownerDocument.baseURI,o=t.__importedScripts?"-"+t.__importedScripts:"";return t.__importedScripts++,"\n//# sourceURL="+n+o+".js\n"}function i(e){var t=e.ownerDocument.createElement("style");return t.textContent=e.textContent,a.resolveUrlsInStyle(t),t}var a=e.path,s=e.rootDocument,c=e.flags,d=e.isIE,l=e.IMPORT_LINK_TYPE,u="link[rel="+l+"]",h={documentSelectors:u,importsSelectors:[u,"link[rel=stylesheet]:not([type])","style:not([type])","script:not([type])",'script[type="application/javascript"]','script[type="text/javascript"]'].join(","),map:{link:"parseLink",script:"parseScript",style:"parseStyle"},dynamicElements:[],parseNext:function(){var e=this.nextToParse();e&&this.parse(e)},parse:function(e){if(this.isParsed(e))return void(c.parse&&console.log("[%s] is already parsed",e.localName));var t=this[this.map[e.localName]];t&&(this.markParsing(e),t.call(this,e))},parseDynamic:function(e,t){this.dynamicElements.push(e),t||this.parseNext()},markParsing:function(e){c.parse&&console.log("parsing",e),this.parsingElement=e},markParsingComplete:function(e){e.__importParsed=!0,this.markDynamicParsingComplete(e),e.__importElement&&(e.__importElement.__importParsed=!0,this.markDynamicParsingComplete(e.__importElement)),this.parsingElement=null,c.parse&&console.log("completed",e)},markDynamicParsingComplete:function(e){var t=this.dynamicElements.indexOf(e);t>=0&&this.dynamicElements.splice(t,1)},parseImport:function(e){if(e["import"]=e.__doc,window.HTMLImports.__importsParsingHook&&window.HTMLImports.__importsParsingHook(e),e["import"]&&(e["import"].__importParsed=!0),this.markParsingComplete(e),e.__resource&&!e.__error?e.dispatchEvent(new CustomEvent("load",{bubbles:!1})):e.dispatchEvent(new CustomEvent("error",{bubbles:!1})),e.__pending)for(var t;e.__pending.length;)t=e.__pending.shift(),t&&t({target:e});this.parseNext()},parseLink:function(e){t(e)?this.parseImport(e):(e.href=e.href,this.parseGeneric(e))},parseStyle:function(e){var t=e;e=i(e),t.__appliedElement=e,e.__importElement=t,this.parseGeneric(e)},parseGeneric:function(e){this.trackElement(e),this.addElementToDocument(e)},rootImportForElement:function(e){for(var t=e;t.ownerDocument.__importLink;)t=t.ownerDocument.__importLink;return t},addElementToDocument:function(e){var t=this.rootImportForElement(e.__importElement||e);t.parentNode.insertBefore(e,t)},trackElement:function(e,t){var n=this,o=function(r){e.removeEventListener("load",o),e.removeEventListener("error",o),t&&t(r),n.markParsingComplete(e),n.parseNext()};if(e.addEventListener("load",o),e.addEventListener("error",o),d&&"style"===e.localName){var r=!1;if(-1==e.textContent.indexOf("@import"))r=!0;else if(e.sheet){r=!0;for(var i,a=e.sheet.cssRules,s=a?a.length:0,c=0;s>c&&(i=a[c]);c++)i.type===CSSRule.IMPORT_RULE&&(r=r&&Boolean(i.styleSheet))}r&&setTimeout(function(){e.dispatchEvent(new CustomEvent("load",{bubbles:!1}))})}},parseScript:function(t){var o=document.createElement("script");o.__importElement=t,o.src=t.src?t.src:n(t),e.currentScript=t,this.trackElement(o,function(t){o.parentNode&&o.parentNode.removeChild(o),e.currentScript=null}),this.addElementToDocument(o)},nextToParse:function(){return this._mayParse=[],!this.parsingElement&&(this.nextToParseInDoc(s)||this.nextToParseDynamic())},nextToParseInDoc:function(e,n){if(e&&this._mayParse.indexOf(e)<0){this._mayParse.push(e);for(var o,r=e.querySelectorAll(this.parseSelectorsForNode(e)),i=0,a=r.length;a>i&&(o=r[i]);i++)if(!this.isParsed(o))return this.hasResource(o)?t(o)?this.nextToParseInDoc(o.__doc,o):o:void 0}return n},nextToParseDynamic:function(){return this.dynamicElements[0]},parseSelectorsForNode:function(e){var t=e.ownerDocument||e;return t===s?this.documentSelectors:this.importsSelectors},isParsed:function(e){return e.__importParsed},needsDynamicParsing:function(e){return this.dynamicElements.indexOf(e)>=0},hasResource:function(e){return!t(e)||void 0!==e.__doc}};e.parser=h,e.IMPORT_SELECTOR=u}),window.HTMLImports.addModule(function(e){function t(e){return n(e,a)}function n(e,t){return"link"===e.localName&&e.getAttribute("rel")===t}function o(e){return!!Object.getOwnPropertyDescriptor(e,"baseURI")}function r(e,t){var n=document.implementation.createHTMLDocument(a);n._URL=t;var r=n.createElement("base");r.setAttribute("href",t),n.baseURI||o(n)||Object.defineProperty(n,"baseURI",{value:t});var i=n.createElement("meta");return i.setAttribute("charset","utf-8"),n.head.appendChild(i),n.head.appendChild(r),n.body.innerHTML=e,window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(n),n}var i=e.flags,a=e.IMPORT_LINK_TYPE,s=e.IMPORT_SELECTOR,c=e.rootDocument,d=e.Loader,l=e.Observer,u=e.parser,h={documents:{},documentPreloadSelectors:s,importsPreloadSelectors:[s].join(","),loadNode:function(e){f.addNode(e)},loadSubtree:function(e){var t=this.marshalNodes(e);f.addNodes(t)},marshalNodes:function(e){return e.querySelectorAll(this.loadSelectorsForNode(e))},loadSelectorsForNode:function(e){var t=e.ownerDocument||e;return t===c?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(e,n,o,a,s){if(i.load&&console.log("loaded",e,n),n.__resource=o,n.__error=a,t(n)){var c=this.documents[e];void 0===c&&(c=a?null:r(o,s||e),c&&(c.__importLink=n,this.bootDocument(c)),this.documents[e]=c),n.__doc=c}u.parseNext()},bootDocument:function(e){this.loadSubtree(e),this.observer.observe(e),u.parseNext()},loadedAll:function(){u.parseNext()}},f=new d(h.loaded.bind(h),h.loadedAll.bind(h));if(h.observer=new l,!document.baseURI){var p={get:function(){var e=document.querySelector("base");return e?e.href:window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",p),Object.defineProperty(c,"baseURI",p)}e.importer=h,e.importLoader=f}),window.HTMLImports.addModule(function(e){var t=e.parser,n=e.importer,o={added:function(e){for(var o,r,i,a,s=0,c=e.length;c>s&&(a=e[s]);s++)o||(o=a.ownerDocument,r=t.isParsed(o)),i=this.shouldLoadNode(a),i&&n.loadNode(a),this.shouldParseNode(a)&&r&&t.parseDynamic(a,i)},shouldLoadNode:function(e){return 1===e.nodeType&&r.call(e,n.loadSelectorsForNode(e))},shouldParseNode:function(e){return 1===e.nodeType&&r.call(e,t.parseSelectorsForNode(e))}};n.observer.addCallback=o.added.bind(o);var r=HTMLElement.prototype.matches||HTMLElement.prototype.matchesSelector||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector}),function(e){function t(){window.HTMLImports.importer.bootDocument(o)}var n=e.initializeModules;e.isIE;if(!e.useNative){n();var o=e.rootDocument;"complete"===document.readyState||"interactive"===document.readyState&&!window.attachEvent?t():document.addEventListener("DOMContentLoaded",t)}}(window.HTMLImports),window.CustomElements=window.CustomElements||{flags:{}},function(e){var t=e.flags,n=[],o=function(e){n.push(e)},r=function(){n.forEach(function(t){t(e)})};e.addModule=o,e.initializeModules=r,e.hasNative=Boolean(document.registerElement),e.isIE=/Trident/.test(navigator.userAgent),e.useNative=!t.register&&e.hasNative&&!window.ShadowDOMPolyfill&&(!window.HTMLImports||window.HTMLImports.useNative)}(window.CustomElements),window.CustomElements.addModule(function(e){function t(e,t){n(e,function(e){return t(e)?!0:void o(e,t)}),o(e,t)}function n(e,t,o){var r=e.firstElementChild;if(!r)for(r=e.firstChild;r&&r.nodeType!==Node.ELEMENT_NODE;)r=r.nextSibling;for(;r;)t(r,o)!==!0&&n(r,t,o),r=r.nextElementSibling;return null}function o(e,n){for(var o=e.shadowRoot;o;)t(o,n),o=o.olderShadowRoot}function r(e,t){i(e,t,[])}function i(e,t,n){if(e=window.wrap(e),!(n.indexOf(e)>=0)){n.push(e);for(var o,r=e.querySelectorAll("link[rel="+a+"]"),s=0,c=r.length;c>s&&(o=r[s]);s++)o["import"]&&i(o["import"],t,n);t(e)}}var a=window.HTMLImports?window.HTMLImports.IMPORT_LINK_TYPE:"none";e.forDocumentTree=r,e.forSubtree=t}),window.CustomElements.addModule(function(e){function t(e,t){return n(e,t)||o(e,t)}function n(t,n){return e.upgrade(t,n)?!0:void(n&&a(t))}function o(e,t){g(e,function(e){return n(e,t)?!0:void 0})}function r(e){L.push(e),E||(E=!0,setTimeout(i))}function i(){E=!1;for(var e,t=L,n=0,o=t.length;o>n&&(e=t[n]);n++)e();L=[]}function a(e){y?r(function(){s(e)}):s(e)}function s(e){ -e.__upgraded__&&!e.__attached&&(e.__attached=!0,e.attachedCallback&&e.attachedCallback())}function c(e){d(e),g(e,function(e){d(e)})}function d(e){y?r(function(){l(e)}):l(e)}function l(e){e.__upgraded__&&e.__attached&&(e.__attached=!1,e.detachedCallback&&e.detachedCallback())}function u(e){for(var t=e,n=window.wrap(document);t;){if(t==n)return!0;t=t.parentNode||t.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&t.host}}function h(e){if(e.shadowRoot&&!e.shadowRoot.__watched){_.dom&&console.log("watching shadow-root for: ",e.localName);for(var t=e.shadowRoot;t;)m(t),t=t.olderShadowRoot}}function f(e,n){if(_.dom){var o=n[0];if(o&&"childList"===o.type&&o.addedNodes&&o.addedNodes){for(var r=o.addedNodes[0];r&&r!==document&&!r.host;)r=r.parentNode;var i=r&&(r.URL||r._URL||r.host&&r.host.localName)||"";i=i.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",n.length,i||"")}var a=u(e);n.forEach(function(e){"childList"===e.type&&(N(e.addedNodes,function(e){e.localName&&t(e,a)}),N(e.removedNodes,function(e){e.localName&&c(e)}))}),_.dom&&console.groupEnd()}function p(e){for(e=window.wrap(e),e||(e=window.wrap(document));e.parentNode;)e=e.parentNode;var t=e.__observer;t&&(f(e,t.takeRecords()),i())}function m(e){if(!e.__observer){var t=new MutationObserver(f.bind(this,e));t.observe(e,{childList:!0,subtree:!0}),e.__observer=t}}function v(e){e=window.wrap(e),_.dom&&console.group("upgradeDocument: ",e.baseURI.split("/").pop());var n=e===window.wrap(document);t(e,n),m(e),_.dom&&console.groupEnd()}function w(e){b(e,v)}var _=e.flags,g=e.forSubtree,b=e.forDocumentTree,y=window.MutationObserver._isPolyfilled&&_["throttle-attached"];e.hasPolyfillMutations=y,e.hasThrottledAttached=y;var E=!1,L=[],N=Array.prototype.forEach.call.bind(Array.prototype.forEach),M=Element.prototype.createShadowRoot;M&&(Element.prototype.createShadowRoot=function(){var e=M.call(this);return window.CustomElements.watchShadow(this),e}),e.watchShadow=h,e.upgradeDocumentTree=w,e.upgradeDocument=v,e.upgradeSubtree=o,e.upgradeAll=t,e.attached=a,e.takeRecords=p}),window.CustomElements.addModule(function(e){function t(t,o){if("template"===t.localName&&window.HTMLTemplateElement&&HTMLTemplateElement.decorate&&HTMLTemplateElement.decorate(t),!t.__upgraded__&&t.nodeType===Node.ELEMENT_NODE){var r=t.getAttribute("is"),i=e.getRegisteredDefinition(t.localName)||e.getRegisteredDefinition(r);if(i&&(r&&i.tag==t.localName||!r&&!i["extends"]))return n(t,i,o)}}function n(t,n,r){return a.upgrade&&console.group("upgrade:",t.localName),n.is&&t.setAttribute("is",n.is),o(t,n),t.__upgraded__=!0,i(t),r&&e.attached(t),e.upgradeSubtree(t,r),a.upgrade&&console.groupEnd(),t}function o(e,t){Object.__proto__?e.__proto__=t.prototype:(r(e,t.prototype,t["native"]),e.__proto__=t.prototype)}function r(e,t,n){for(var o={},r=t;r!==n&&r!==HTMLElement.prototype;){for(var i,a=Object.getOwnPropertyNames(r),s=0;i=a[s];s++)o[i]||(Object.defineProperty(e,i,Object.getOwnPropertyDescriptor(r,i)),o[i]=1);r=Object.getPrototypeOf(r)}}function i(e){e.createdCallback&&e.createdCallback()}var a=e.flags;e.upgrade=t,e.upgradeWithDefinition=n,e.implementPrototype=o}),window.CustomElements.addModule(function(e){function t(t,o){var c=o||{};if(!t)throw new Error("document.registerElement: first argument `name` must not be empty");if(t.indexOf("-")<0)throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(t)+"'.");if(r(t))throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '"+String(t)+"'. The type name is invalid.");if(d(t))throw new Error("DuplicateDefinitionError: a type with name '"+String(t)+"' is already registered");return c.prototype||(c.prototype=Object.create(HTMLElement.prototype)),c.__name=t.toLowerCase(),c["extends"]&&(c["extends"]=c["extends"].toLowerCase()),c.lifecycle=c.lifecycle||{},c.ancestry=i(c["extends"]),a(c),s(c),n(c.prototype),l(c.__name,c),c.ctor=u(c),c.ctor.prototype=c.prototype,c.prototype.constructor=c.ctor,e.ready&&v(document),c.ctor}function n(e){if(!e.setAttribute._polyfilled){var t=e.setAttribute;e.setAttribute=function(e,n){o.call(this,e,n,t)};var n=e.removeAttribute;e.removeAttribute=function(e){o.call(this,e,null,n)},e.setAttribute._polyfilled=!0}}function o(e,t,n){e=e.toLowerCase();var o=this.getAttribute(e);n.apply(this,arguments);var r=this.getAttribute(e);this.attributeChangedCallback&&r!==o&&this.attributeChangedCallback(e,o,r)}function r(e){for(var t=0;t=0&&g(o,HTMLElement),o)}function p(e,t){var n=e[t];e[t]=function(){var e=n.apply(this,arguments);return w(e),e}}var m,v=(e.isIE,e.upgradeDocumentTree),w=e.upgradeAll,_=e.upgradeWithDefinition,g=e.implementPrototype,b=e.useNative,y=["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","font-face-format","font-face-name","missing-glyph"],E={},L="http://www.w3.org/1999/xhtml",N=document.createElement.bind(document),M=document.createElementNS.bind(document);m=Object.__proto__||b?function(e,t){return e instanceof t}:function(e,t){if(e instanceof t)return!0;for(var n=e;n;){if(n===t.prototype)return!0;n=n.__proto__}return!1},p(Node.prototype,"cloneNode"),p(document,"importNode"),document.registerElement=t,document.createElement=f,document.createElementNS=h,e.registry=E,e["instanceof"]=m,e.reservedTagList=y,e.getRegisteredDefinition=d,document.register=document.registerElement}),function(e){function t(){i(window.wrap(document)),window.CustomElements.ready=!0;var e=window.requestAnimationFrame||function(e){setTimeout(e,16)};e(function(){setTimeout(function(){window.CustomElements.readyTime=Date.now(),window.HTMLImports&&(window.CustomElements.elapsed=window.CustomElements.readyTime-window.HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})})}var n=e.useNative,o=e.initializeModules;e.isIE;if(n){var r=function(){};e.watchShadow=r,e.upgrade=r,e.upgradeAll=r,e.upgradeDocumentTree=r,e.upgradeSubtree=r,e.takeRecords=r,e["instanceof"]=function(e,t){return e instanceof t}}else o();var i=e.upgradeDocumentTree,a=e.upgradeDocument;if(window.wrap||(window.ShadowDOMPolyfill?(window.wrap=window.ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=window.ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}),window.HTMLImports&&(window.HTMLImports.__importsParsingHook=function(e){e["import"]&&a(wrap(e["import"]))}),"complete"===document.readyState||e.flags.eager)t();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var s=window.HTMLImports&&!window.HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(s,t)}else t()}(window.CustomElements),function(e){var t=document.createElement("style");t.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; position: relative; } \n";var n=document.querySelector("head");n.insertBefore(t,n.firstChild)}(window.WebComponents); \ No newline at end of file +// @version 0.7.23 +!function(){window.WebComponents=window.WebComponents||{flags:{}};var e="webcomponents-lite.js",t=document.querySelector('script[src*="'+e+'"]'),n={};if(!n.noOpts){if(location.search.slice(1).split("&").forEach(function(e){var t,o=e.split("=");o[0]&&(t=o[0].match(/wc-(.+)/))&&(n[t[1]]=o[1]||!0)}),t)for(var o,r=0;o=t.attributes[r];r++)"src"!==o.name&&(n[o.name]=o.value||!0);if(n.log&&n.log.split){var i=n.log.split(",");n.log={},i.forEach(function(e){n.log[e]=!0})}else n.log={}}n.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.CustomElements.flags.register=n.register),WebComponents.flags=n}(),function(e){"use strict";function t(e){return void 0!==h[e]}function n(){s.call(this),this._isInvalid=!0}function o(e){return""==e&&n.call(this),e.toLowerCase()}function r(e){var t=e.charCodeAt(0);return t>32&&t<127&&[34,35,60,62,63,96].indexOf(t)==-1?e:encodeURIComponent(e)}function i(e){var t=e.charCodeAt(0);return t>32&&t<127&&[34,35,60,62,96].indexOf(t)==-1?e:encodeURIComponent(e)}function a(e,a,s){function c(e){g.push(e)}var d=a||"scheme start",l=0,u="",w=!1,_=!1,g=[];e:for(;(e[l-1]!=p||0==l)&&!this._isInvalid;){var b=e[l];switch(d){case"scheme start":if(!b||!m.test(b)){if(a){c("Invalid scheme.");break e}u="",d="no scheme";continue}u+=b.toLowerCase(),d="scheme";break;case"scheme":if(b&&v.test(b))u+=b.toLowerCase();else{if(":"!=b){if(a){if(p==b)break e;c("Code point not allowed in scheme: "+b);break e}u="",l=0,d="no scheme";continue}if(this._scheme=u,u="",a)break e;t(this._scheme)&&(this._isRelative=!0),d="file"==this._scheme?"relative":this._isRelative&&s&&s._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==b?(this._query="?",d="query"):"#"==b?(this._fragment="#",d="fragment"):p!=b&&"\t"!=b&&"\n"!=b&&"\r"!=b&&(this._schemeData+=r(b));break;case"no scheme":if(s&&t(s._scheme)){d="relative";continue}c("Missing scheme."),n.call(this);break;case"relative or authority":if("/"!=b||"/"!=e[l+1]){c("Expected /, got: "+b),d="relative";continue}d="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=s._scheme),p==b){this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._username=s._username,this._password=s._password;break e}if("/"==b||"\\"==b)"\\"==b&&c("\\ is an invalid code point."),d="relative slash";else if("?"==b)this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query="?",this._username=s._username,this._password=s._password,d="query";else{if("#"!=b){var y=e[l+1],E=e[l+2];("file"!=this._scheme||!m.test(b)||":"!=y&&"|"!=y||p!=E&&"/"!=E&&"\\"!=E&&"?"!=E&&"#"!=E)&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password,this._path=s._path.slice(),this._path.pop()),d="relative path";continue}this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._fragment="#",this._username=s._username,this._password=s._password,d="fragment"}break;case"relative slash":if("/"!=b&&"\\"!=b){"file"!=this._scheme&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password),d="relative path";continue}"\\"==b&&c("\\ is an invalid code point."),d="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=b){c("Expected '/', got: "+b),d="authority ignore slashes";continue}d="authority second slash";break;case"authority second slash":if(d="authority ignore slashes","/"!=b){c("Expected '/', got: "+b);continue}break;case"authority ignore slashes":if("/"!=b&&"\\"!=b){d="authority";continue}c("Expected authority, got: "+b);break;case"authority":if("@"==b){w&&(c("@ already seen."),u+="%40"),w=!0;for(var L=0;L>>0)+(t++ +"__")};n.prototype={set:function(t,n){var o=t[this.name];return o&&o[0]===t?o[1]=n:e(t,this.name,{value:[t,n],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0},"delete":function(e){var t=e[this.name];return!(!t||t[0]!==e)&&(t[0]=t[1]=void 0,!0)},has:function(e){var t=e[this.name];return!!t&&t[0]===e}},window.WeakMap=n}(),function(e){function t(e){b.push(e),g||(g=!0,m(o))}function n(e){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(e)||e}function o(){g=!1;var e=b;b=[],e.sort(function(e,t){return e.uid_-t.uid_});var t=!1;e.forEach(function(e){var n=e.takeRecords();r(e),n.length&&(e.callback_(n,e),t=!0)}),t&&o()}function r(e){e.nodes_.forEach(function(t){var n=v.get(t);n&&n.forEach(function(t){t.observer===e&&t.removeTransientObservers()})})}function i(e,t){for(var n=e;n;n=n.parentNode){var o=v.get(n);if(o)for(var r=0;r0){var r=n[o-1],i=f(r,e);if(i)return void(n[o-1]=i)}else t(this.observer);n[o]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=v.get(e);t||v.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=v.get(e),n=0;n":return">";case" ":return" "}}function t(t){return t.replace(u,e)}var n="undefined"==typeof HTMLTemplateElement;/Trident/.test(navigator.userAgent)&&!function(){var e=document.importNode;document.importNode=function(){var t=e.apply(document,arguments);if(t.nodeType===Node.DOCUMENT_FRAGMENT_NODE){var n=document.createDocumentFragment();return n.appendChild(t),n}return t}}();var o=function(){if(!n){var e=document.createElement("template"),t=document.createElement("template");t.content.appendChild(document.createElement("div")),e.content.appendChild(t);var o=e.cloneNode(!0);return 0===o.content.childNodes.length||0===o.content.firstChild.content.childNodes.length}}(),r="template",i=function(){};if(n){var a=document.implementation.createHTMLDocument("template"),s=!0,c=document.createElement("style");c.textContent=r+"{display:none;}";var d=document.head;d.insertBefore(c,d.firstElementChild),i.prototype=Object.create(HTMLElement.prototype),i.decorate=function(e){if(!e.content){e.content=a.createDocumentFragment();for(var n;n=e.firstChild;)e.content.appendChild(n);if(e.cloneNode=function(e){return i.cloneNode(this,e)},s)try{Object.defineProperty(e,"innerHTML",{get:function(){for(var e="",n=this.content.firstChild;n;n=n.nextSibling)e+=n.outerHTML||t(n.data);return e},set:function(e){for(a.body.innerHTML=e,i.bootstrap(a);this.content.firstChild;)this.content.removeChild(this.content.firstChild);for(;a.body.firstChild;)this.content.appendChild(a.body.firstChild)},configurable:!0})}catch(o){s=!1}i.bootstrap(e.content)}},i.bootstrap=function(e){for(var t,n=e.querySelectorAll(r),o=0,a=n.length;o]/g}if(n||o){var h=Node.prototype.cloneNode;i.cloneNode=function(e,t){var n=h.call(e,!1);return this.decorate&&this.decorate(n),t&&(n.content.appendChild(h.call(e.content,!0)),this.fixClonedDom(n.content,e.content)),n},i.fixClonedDom=function(e,t){if(t.querySelectorAll)for(var n,o,i=t.querySelectorAll(r),a=e.querySelectorAll(r),s=0,c=a.length;s=200&&e.status<300||304===e.status||0===e.status},load:function(n,o,r){var i=new XMLHttpRequest;return(e.flags.debug||e.flags.bust)&&(n+="?"+Math.random()),i.open("GET",n,t.async),i.addEventListener("readystatechange",function(e){if(4===i.readyState){var n=null;try{var a=i.getResponseHeader("Location");a&&(n="/"===a.substr(0,1)?location.origin+a:a)}catch(e){console.error(e.message)}o.call(r,!t.ok(i)&&i,i.response||i.responseText,n)}}),i.send(),i},loadDocument:function(e,t,n){this.load(e,t,n).responseType="document"}};e.xhr=t}),window.HTMLImports.addModule(function(e){var t=e.xhr,n=e.flags,o=function(e,t){this.cache={},this.onload=e,this.oncomplete=t,this.inflight=0,this.pending={}};o.prototype={addNodes:function(e){this.inflight+=e.length;for(var t,n=0,o=e.length;n-1?atob(a):decodeURIComponent(a),setTimeout(function(){this.receive(e,o,null,a)}.bind(this),0)}else{var s=function(t,n,r){this.receive(e,o,t,n,r)}.bind(this);t.load(e,s)}else setTimeout(function(){this.receive(e,o,{error:"href must be specified"},null)}.bind(this),0)},receive:function(e,t,n,o,r){this.cache[e]=o;for(var i,a=this.pending[e],s=0,c=a.length;s=0&&this.dynamicElements.splice(t,1)},parseImport:function(e){if(e["import"]=e.__doc,window.HTMLImports.__importsParsingHook&&window.HTMLImports.__importsParsingHook(e),e["import"]&&(e["import"].__importParsed=!0),this.markParsingComplete(e),e.__resource&&!e.__error?e.dispatchEvent(new CustomEvent("load",{bubbles:!1})):e.dispatchEvent(new CustomEvent("error",{bubbles:!1})),e.__pending)for(var t;e.__pending.length;)t=e.__pending.shift(),t&&t({target:e});this.parseNext()},parseLink:function(e){t(e)?this.parseImport(e):(e.href=e.href,this.parseGeneric(e))},parseStyle:function(e){var t=e;e=i(e),t.__appliedElement=e,e.__importElement=t,this.parseGeneric(e)},parseGeneric:function(e){this.trackElement(e),this.addElementToDocument(e)},rootImportForElement:function(e){for(var t=e;t.ownerDocument.__importLink;)t=t.ownerDocument.__importLink;return t},addElementToDocument:function(e){var t=this.rootImportForElement(e.__importElement||e);t.parentNode.insertBefore(e,t)},trackElement:function(e,t){var n=this,o=function(r){e.removeEventListener("load",o),e.removeEventListener("error",o),t&&t(r),n.markParsingComplete(e),n.parseNext()};if(e.addEventListener("load",o),e.addEventListener("error",o),d&&"style"===e.localName){var r=!1;if(e.textContent.indexOf("@import")==-1)r=!0;else if(e.sheet){r=!0;for(var i,a=e.sheet.cssRules,s=a?a.length:0,c=0;c=0},hasResource:function(e){return!t(e)||void 0!==e.__doc}};e.parser=h,e.IMPORT_SELECTOR=u}),window.HTMLImports.addModule(function(e){function t(e){return n(e,a)}function n(e,t){return"link"===e.localName&&e.getAttribute("rel")===t}function o(e){return!!Object.getOwnPropertyDescriptor(e,"baseURI")}function r(e,t){var n=document.implementation.createHTMLDocument(a);n._URL=t;var r=n.createElement("base");r.setAttribute("href",t),n.baseURI||o(n)||Object.defineProperty(n,"baseURI",{value:t});var i=n.createElement("meta");return i.setAttribute("charset","utf-8"),n.head.appendChild(i),n.head.appendChild(r),n.body.innerHTML=e,window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(n),n}var i=e.flags,a=e.IMPORT_LINK_TYPE,s=e.IMPORT_SELECTOR,c=e.rootDocument,d=e.Loader,l=e.Observer,u=e.parser,h={documents:{},documentPreloadSelectors:s,importsPreloadSelectors:[s].join(","),loadNode:function(e){f.addNode(e)},loadSubtree:function(e){var t=this.marshalNodes(e);f.addNodes(t)},marshalNodes:function(e){return e.querySelectorAll(this.loadSelectorsForNode(e))},loadSelectorsForNode:function(e){var t=e.ownerDocument||e;return t===c?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(e,n,o,a,s){if(i.load&&console.log("loaded",e,n),n.__resource=o,n.__error=a,t(n)){var c=this.documents[e];void 0===c&&(c=a?null:r(o,s||e),c&&(c.__importLink=n,this.bootDocument(c)),this.documents[e]=c),n.__doc=c}u.parseNext()},bootDocument:function(e){this.loadSubtree(e),this.observer.observe(e),u.parseNext()},loadedAll:function(){u.parseNext()}},f=new d(h.loaded.bind(h),h.loadedAll.bind(h));if(h.observer=new l,!document.baseURI){var p={get:function(){var e=document.querySelector("base");return e?e.href:window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",p),Object.defineProperty(c,"baseURI",p)}e.importer=h,e.importLoader=f}),window.HTMLImports.addModule(function(e){var t=e.parser,n=e.importer,o={added:function(e){for(var o,r,i,a,s=0,c=e.length;s=0)){n.push(e);for(var o,r=e.querySelectorAll("link[rel="+a+"]"),s=0,c=r.length;s=0&&g(o,HTMLElement),o)}function p(e,t){var n=e[t];e[t]=function(){var e=n.apply(this,arguments);return w(e),e}}var m,v=(e.isIE,e.upgradeDocumentTree),w=e.upgradeAll,_=e.upgradeWithDefinition,g=e.implementPrototype,b=e.useNative,y=["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","font-face-format","font-face-name","missing-glyph"],E={},L="http://www.w3.org/1999/xhtml",N=document.createElement.bind(document),M=document.createElementNS.bind(document);m=Object.__proto__||b?function(e,t){return e instanceof t}:function(e,t){if(e instanceof t)return!0;for(var n=e;n;){if(n===t.prototype)return!0;n=n.__proto__}return!1},p(Node.prototype,"cloneNode"),p(document,"importNode"),document.registerElement=t,document.createElement=f,document.createElementNS=h,e.registry=E,e["instanceof"]=m,e.reservedTagList=y,e.getRegisteredDefinition=d,document.register=document.registerElement}),function(e){function t(){i(window.wrap(document)),window.CustomElements.ready=!0;var e=window.requestAnimationFrame||function(e){setTimeout(e,16)};e(function(){setTimeout(function(){window.CustomElements.readyTime=Date.now(),window.HTMLImports&&(window.CustomElements.elapsed=window.CustomElements.readyTime-window.HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})})}var n=e.useNative,o=e.initializeModules;e.isIE;if(n){var r=function(){};e.watchShadow=r,e.upgrade=r,e.upgradeAll=r,e.upgradeDocumentTree=r,e.upgradeSubtree=r,e.takeRecords=r,e["instanceof"]=function(e,t){return e instanceof t}}else o();var i=e.upgradeDocumentTree,a=e.upgradeDocument;if(window.wrap||(window.ShadowDOMPolyfill?(window.wrap=window.ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=window.ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}),window.HTMLImports&&(window.HTMLImports.__importsParsingHook=function(e){e["import"]&&a(wrap(e["import"]))}),"complete"===document.readyState||e.flags.eager)t();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var s=window.HTMLImports&&!window.HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(s,t)}else t()}(window.CustomElements),function(e){var t=document.createElement("style");t.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; position: relative; } \n";var n=document.querySelector("head");n.insertBefore(t,n.firstChild)}(window.WebComponents); \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/webcomponents-lite.min.js.gz b/homeassistant/components/frontend/www_static/webcomponents-lite.min.js.gz index 0bd0568f231d72b785de5e0e10c0a21228f6b5c7..c5fe12d2303e5b2d7e1f40f018bf774b42f15b6d 100644 GIT binary patch literal 12360 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 literal 12355 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 Date: Fri, 9 Dec 2016 08:19:14 +0100 Subject: [PATCH 062/141] Pilight receive match fix for bug 4637 (#4639) * Pilight: dont protocol as list in COMMAND_SCHEMA As described in bug #4637 the protocol should not be wrapped in a list in the spec of COMMAND_SCHEMA because this causes the component to never successfully match any received rf code. As pointed ot in PR #4639 the easiest way to do this, is to not derive COMMAND_SCHEMA from RF_CODE_SCHEMA and specify protocol as simple string there. This fixes bug #4637. Signed-off-by: Jan Losinski * Pilight: Add "unitcode" to command schema. This adds "unitcode" to the COMMAND_SCHEMA. It is used for example in the brennenstuhl protocol of pilight. Signed-off-by: Jan Losinski --- homeassistant/components/switch/pilight.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/switch/pilight.py b/homeassistant/components/switch/pilight.py index 6e16c9fa2e5..a052848cb21 100644 --- a/homeassistant/components/switch/pilight.py +++ b/homeassistant/components/switch/pilight.py @@ -11,7 +11,8 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv import homeassistant.components.pilight as pilight from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) -from homeassistant.const import (CONF_NAME, CONF_ID, CONF_SWITCHES, CONF_STATE) +from homeassistant.const import (CONF_NAME, CONF_ID, CONF_SWITCHES, CONF_STATE, + CONF_PROTOCOL) _LOGGER = logging.getLogger(__name__) @@ -21,13 +22,16 @@ CONF_ON_CODE = 'on_code' CONF_ON_CODE_RECIEVE = 'on_code_receive' CONF_SYSTEMCODE = 'systemcode' CONF_UNIT = 'unit' +CONF_UNITCODE = 'unitcode' DEPENDENCIES = ['pilight'] -COMMAND_SCHEMA = pilight.RF_CODE_SCHEMA.extend({ +COMMAND_SCHEMA = vol.Schema({ + vol.Optional(CONF_PROTOCOL): cv.string, vol.Optional('on'): cv.positive_int, vol.Optional('off'): cv.positive_int, vol.Optional(CONF_UNIT): cv.positive_int, + vol.Optional(CONF_UNITCODE): cv.positive_int, vol.Optional(CONF_ID): cv.positive_int, vol.Optional(CONF_STATE): cv.string, vol.Optional(CONF_SYSTEMCODE): cv.positive_int, From 0bf9e6d4bb1d38a782824fb8af89ec9bb8406247 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 9 Dec 2016 08:24:03 +0100 Subject: [PATCH 063/141] Bugfix error on automation reload (#4823) --- homeassistant/components/automation/state.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/homeassistant/components/automation/state.py b/homeassistant/components/automation/state.py index fb146991602..65cca462ed9 100644 --- a/homeassistant/components/automation/state.py +++ b/homeassistant/components/automation/state.py @@ -64,10 +64,19 @@ def async_trigger(hass, config, action): call_action() return + @callback + def clear_listener(): + """Clear all unsub listener.""" + nonlocal async_remove_state_for_cancel + nonlocal async_remove_state_for_listener + async_remove_state_for_listener = None + async_remove_state_for_cancel = None + @callback def state_for_listener(now): """Fire on state changes after a delay and calls action.""" async_remove_state_for_cancel() + clear_listener() call_action() @callback @@ -77,6 +86,7 @@ def async_trigger(hass, config, action): return async_remove_state_for_listener() async_remove_state_for_cancel() + clear_listener() async_remove_state_for_listener = async_track_point_in_utc_time( hass, state_for_listener, dt_util.utcnow() + time_delta) From 0aac4d64e1d8336ebe71fe108245409646a82c75 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 9 Dec 2016 01:26:02 -0600 Subject: [PATCH 064/141] Add away mode for Radio Thermostat/3M Filtrete (#4793) --- .../components/climate/radiotherm.py | 49 +++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/climate/radiotherm.py b/homeassistant/components/climate/radiotherm.py index d06e148cfdd..9a0e5666036 100644 --- a/homeassistant/components/climate/radiotherm.py +++ b/homeassistant/components/climate/radiotherm.py @@ -23,10 +23,19 @@ ATTR_FAN = 'fan' ATTR_MODE = 'mode' CONF_HOLD_TEMP = 'hold_temp' +CONF_AWAY_TEMPERATURE_HEAT = 'away_temperature_heat' +CONF_AWAY_TEMPERATURE_COOL = 'away_temperature_cool' + +DEFAULT_AWAY_TEMPERATURE_HEAT = 60 +DEFAULT_AWAY_TEMPERATURE_COOL = 85 PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_HOST): vol.All(cv.ensure_list, [cv.string]), vol.Optional(CONF_HOLD_TEMP, default=False): cv.boolean, + vol.Optional(CONF_AWAY_TEMPERATURE_HEAT, + default=DEFAULT_AWAY_TEMPERATURE_HEAT): vol.Coerce(float), + vol.Optional(CONF_AWAY_TEMPERATURE_COOL, + default=DEFAULT_AWAY_TEMPERATURE_COOL): vol.Coerce(float), }) @@ -45,12 +54,16 @@ def setup_platform(hass, config, add_devices, discovery_info=None): return False hold_temp = config.get(CONF_HOLD_TEMP) + away_temps = [ + config.get(CONF_AWAY_TEMPERATURE_HEAT), + config.get(CONF_AWAY_TEMPERATURE_COOL) + ] tstats = [] for host in hosts: try: tstat = radiotherm.get_thermostat(host) - tstats.append(RadioThermostat(tstat, hold_temp)) + tstats.append(RadioThermostat(tstat, hold_temp, away_temps)) except OSError: _LOGGER.exception("Unable to connect to Radio Thermostat: %s", host) @@ -61,7 +74,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class RadioThermostat(ClimateDevice): """Representation of a Radio Thermostat.""" - def __init__(self, device, hold_temp): + def __init__(self, device, hold_temp, away_temps): """Initialize the thermostat.""" self.device = device self.set_time() @@ -71,7 +84,10 @@ class RadioThermostat(ClimateDevice): self._name = None self._fmode = None self._tmode = None - self.hold_temp = hold_temp + self._hold_temp = hold_temp + self._away = False + self._away_temps = away_temps + self._prev_temp = None self.update() self._operation_list = [STATE_AUTO, STATE_COOL, STATE_HEAT, STATE_OFF] @@ -113,6 +129,11 @@ class RadioThermostat(ClimateDevice): """Return the temperature we try to reach.""" return self._target_temperature + @property + def is_away_mode_on(self): + """Return true if away mode is on.""" + return self._away + def update(self): """Update the data from the thermostat.""" self._current_temperature = self.device.temp['raw'] @@ -138,7 +159,7 @@ class RadioThermostat(ClimateDevice): self.device.t_cool = round(temperature * 2.0) / 2.0 elif self._current_operation == STATE_HEAT: self.device.t_heat = round(temperature * 2.0) / 2.0 - if self.hold_temp: + if self._hold_temp or self._away: self.device.hold = 1 else: self.device.hold = 0 @@ -162,3 +183,23 @@ class RadioThermostat(ClimateDevice): self.device.t_cool = round(self._target_temperature * 2.0) / 2.0 elif operation_mode == STATE_HEAT: self.device.t_heat = round(self._target_temperature * 2.0) / 2.0 + + def turn_away_mode_on(self): + """Turn away on. + + The RTCOA app simulates away mode by using a hold. + """ + away_temp = None + if not self._away: + self._prev_temp = self._target_temperature + if self._current_operation == STATE_HEAT: + away_temp = self._away_temps[0] + elif self._current_operation == STATE_COOL: + away_temp = self._away_temps[1] + self._away = True + self.set_temperature(temperature=away_temp) + + def turn_away_mode_off(self): + """Turn away off.""" + self._away = False + self.set_temperature(temperature=self._prev_temp) From d02899216dae86c0b41d60ceefb4aab3a1be1222 Mon Sep 17 00:00:00 2001 From: Keaton Taylor Date: Fri, 9 Dec 2016 10:45:14 -0600 Subject: [PATCH 065/141] Prevent emulated hue discovery by hue component (#4819) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Prevent emulated hue discovery Test for “HASS Bridge” in discovery info, pass if found, else try and setup the bridge. * Solved coding error Duplicate commands and return false added for component. --- homeassistant/components/light/hue.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/homeassistant/components/light/hue.py b/homeassistant/components/light/hue.py index 8fd8a6ef097..da2158ba78d 100644 --- a/homeassistant/components/light/hue.py +++ b/homeassistant/components/light/hue.py @@ -90,6 +90,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if discovery_info is not None: host = urlparse(discovery_info[1]).hostname + + if "HASS Bridge" in discovery_info[0]: + _LOGGER.info('Emulated hue found, will not add') + return False else: host = config.get(CONF_HOST, None) From 1547045f2c292a3558b9dccac48a16aefc541533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Oldag?= Date: Fri, 9 Dec 2016 17:52:14 +0100 Subject: [PATCH 066/141] Flic: Support ignoring individual click types. (#4827) --- .../components/binary_sensor/flic.py | 59 +++++++++++++++---- 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/binary_sensor/flic.py b/homeassistant/components/binary_sensor/flic.py index 63323155d31..92301330605 100644 --- a/homeassistant/components/binary_sensor/flic.py +++ b/homeassistant/components/binary_sensor/flic.py @@ -17,6 +17,13 @@ REQUIREMENTS = ['https://github.com/soldag/pyflic/archive/0.4.zip#pyflic==0.4'] _LOGGER = logging.getLogger(__name__) +CLICK_TYPE_SINGLE = "single" +CLICK_TYPE_DOUBLE = "double" +CLICK_TYPE_HOLD = "hold" +CLICK_TYPES = [CLICK_TYPE_SINGLE, CLICK_TYPE_DOUBLE, CLICK_TYPE_HOLD] + +CONF_IGNORED_CLICK_TYPES = "ignored_click_types" + EVENT_NAME = "flic_click" EVENT_DATA_NAME = "button_name" EVENT_DATA_ADDRESS = "button_address" @@ -26,7 +33,9 @@ EVENT_DATA_TYPE = "click_type" PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_HOST, default='localhost'): cv.string, vol.Optional(CONF_PORT, default=5551): cv.port, - vol.Optional(CONF_DISCOVERY, default=True): cv.boolean + vol.Optional(CONF_DISCOVERY, default=True): cv.boolean, + vol.Optional(CONF_IGNORED_CLICK_TYPES): vol.All(cv.ensure_list, + [vol.In(CLICK_TYPES)]) }) @@ -93,7 +102,8 @@ def start_scanning(hass, config, async_add_entities, client): @asyncio.coroutine def async_setup_button(hass, config, async_add_entities, client, address): """Setup single button device.""" - button = FlicButton(hass, client, address) + ignored_click_types = config.get(CONF_IGNORED_CLICK_TYPES) + button = FlicButton(hass, client, address, ignored_click_types) _LOGGER.info("Connected to button (%s)", address) yield from async_add_entities([button]) @@ -117,25 +127,47 @@ def async_get_verified_addresses(client): class FlicButton(BinarySensorDevice): """Representation of a flic button.""" - def __init__(self, hass, client, address): + def __init__(self, hass, client, address, ignored_click_types): """Initialize the flic button.""" import pyflic self._hass = hass self._address = address self._is_down = False - self._click_types = { - pyflic.ClickType.ButtonSingleClick: "single", - pyflic.ClickType.ButtonDoubleClick: "double", - pyflic.ClickType.ButtonHold: "hold", + self._ignored_click_types = ignored_click_types or [] + self._hass_click_types = { + pyflic.ClickType.ButtonClick: CLICK_TYPE_SINGLE, + pyflic.ClickType.ButtonSingleClick: CLICK_TYPE_SINGLE, + pyflic.ClickType.ButtonDoubleClick: CLICK_TYPE_DOUBLE, + pyflic.ClickType.ButtonHold: CLICK_TYPE_HOLD, } - # Initialize connection channel - self._channel = pyflic.ButtonConnectionChannel(self._address) - self._channel.on_button_up_or_down = self._on_up_down - self._channel.on_button_single_or_double_click_or_hold = self._on_click + self._channel = self._create_channel() client.add_connection_channel(self._channel) + def _create_channel(self): + """Create a new connection channel to the button.""" + import pyflic + + channel = pyflic.ButtonConnectionChannel(self._address) + channel.on_button_up_or_down = self._on_up_down + + # If all types of clicks should be ignored, skip registering callbacks + if set(self._ignored_click_types) == set(CLICK_TYPES): + return channel + + if CLICK_TYPE_DOUBLE in self._ignored_click_types: + # Listen to all but double click type events + channel.on_button_click_or_hold = self._on_click + elif CLICK_TYPE_HOLD in self._ignored_click_types: + # Listen to all but hold click type events + channel.on_button_single_or_double_click = self._on_click + else: + # Listen to all click type events + channel.on_button_single_or_double_click_or_hold = self._on_click + + return channel + @property def name(self): """Return the name of the device.""" @@ -176,13 +208,14 @@ class FlicButton(BinarySensorDevice): def _on_click(self, channel, click_type, was_queued, time_diff): """Fire click event, if event was not queued.""" - if was_queued: + hass_click_type = self._hass_click_types[click_type] + if was_queued or hass_click_type in self._ignored_click_types: return self._hass.bus.fire(EVENT_NAME, { EVENT_DATA_NAME: self.name, EVENT_DATA_ADDRESS: self.address, - EVENT_DATA_TYPE: self._click_types[click_type] + EVENT_DATA_TYPE: hass_click_type }) def _connection_status_changed(self, channel, From 64de1c9777f09b641694a3c53375bac5db9d4fdf Mon Sep 17 00:00:00 2001 From: Josh Nichols Date: Fri, 9 Dec 2016 14:04:40 -0500 Subject: [PATCH 067/141] 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 27573a2c587..b67ef6f9d2b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -167,7 +167,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 167260bcc65317aa74212bbcb78ecf14c20263e2 Mon Sep 17 00:00:00 2001 From: r-jordan Date: Sat, 10 Dec 2016 11:36:35 +0100 Subject: [PATCH 068/141] [climate.generic_thermostat] Make tolerance work both ways (#4830) --- .../components/climate/generic_thermostat.py | 36 ++++---- .../climate/test_generic_thermostat.py | 84 ++++++++++++------- 2 files changed, 73 insertions(+), 47 deletions(-) diff --git a/homeassistant/components/climate/generic_thermostat.py b/homeassistant/components/climate/generic_thermostat.py index 1b3d20d8b59..a40795c37c5 100644 --- a/homeassistant/components/climate/generic_thermostat.py +++ b/homeassistant/components/climate/generic_thermostat.py @@ -198,24 +198,30 @@ class GenericThermostat(ClimateDevice): return if self.ac_mode: - too_hot = self._cur_temp - self._target_temp > self._tolerance is_cooling = self._is_device_active - if too_hot and not is_cooling: - _LOGGER.info('Turning on AC %s', self.heater_entity_id) - switch.turn_on(self.hass, self.heater_entity_id) - elif not too_hot and is_cooling: - _LOGGER.info('Turning off AC %s', self.heater_entity_id) - switch.turn_off(self.hass, self.heater_entity_id) + if is_cooling: + too_cold = self._target_temp - self._cur_temp > self._tolerance + if too_cold: + _LOGGER.info('Turning off AC %s', self.heater_entity_id) + switch.turn_off(self.hass, self.heater_entity_id) + else: + too_hot = self._cur_temp - self._target_temp > self._tolerance + if too_hot: + _LOGGER.info('Turning on AC %s', self.heater_entity_id) + switch.turn_on(self.hass, self.heater_entity_id) else: - too_cold = self._target_temp - self._cur_temp > self._tolerance is_heating = self._is_device_active - - if too_cold and not is_heating: - _LOGGER.info('Turning on heater %s', self.heater_entity_id) - switch.turn_on(self.hass, self.heater_entity_id) - elif not too_cold and is_heating: - _LOGGER.info('Turning off heater %s', self.heater_entity_id) - switch.turn_off(self.hass, self.heater_entity_id) + if is_heating: + too_hot = self._cur_temp - self._target_temp > self._tolerance + if too_hot: + _LOGGER.info('Turning off heater %s', + self.heater_entity_id) + switch.turn_off(self.hass, self.heater_entity_id) + else: + too_cold = self._target_temp - self._cur_temp > self._tolerance + if too_cold: + _LOGGER.info('Turning on heater %s', self.heater_entity_id) + switch.turn_on(self.hass, self.heater_entity_id) @property def _is_device_active(self): diff --git a/tests/components/climate/test_generic_thermostat.py b/tests/components/climate/test_generic_thermostat.py index 1730c3e003b..7c4ee8db58f 100644 --- a/tests/components/climate/test_generic_thermostat.py +++ b/tests/components/climate/test_generic_thermostat.py @@ -181,34 +181,10 @@ class TestClimateGenericThermostat(unittest.TestCase): self.assertEqual(SERVICE_TURN_OFF, call.service) self.assertEqual(ENT_SWITCH, call.data['entity_id']) - def test_set_temp_change_heater_on(self): - """Test if temperature change turn heater on.""" - self._setup_switch(False) - climate.set_temperature(self.hass, 30) - self.hass.block_till_done() - self._setup_sensor(25) - self.hass.block_till_done() - self.assertEqual(1, len(self.calls)) - call = self.calls[0] - self.assertEqual('switch', call.domain) - self.assertEqual(SERVICE_TURN_ON, call.service) - self.assertEqual(ENT_SWITCH, call.data['entity_id']) - - def test_temp_change_heater_off(self): - """Test if temperature change turn heater off.""" - self._setup_switch(True) - climate.set_temperature(self.hass, 25) - self.hass.block_till_done() - self._setup_sensor(30) - self.hass.block_till_done() - self.assertEqual(1, len(self.calls)) - call = self.calls[0] - self.assertEqual('switch', call.domain) - self.assertEqual(SERVICE_TURN_OFF, call.service) - self.assertEqual(ENT_SWITCH, call.data['entity_id']) - def test_temp_change_heater_on_within_tolerance(self): - """Test if temperature change turn heater on within tolerance.""" + """Test if temperature change doesn't turn heater on within + tolerance. + """ self._setup_switch(False) climate.set_temperature(self.hass, 30) self.hass.block_till_done() @@ -217,9 +193,7 @@ class TestClimateGenericThermostat(unittest.TestCase): self.assertEqual(0, len(self.calls)) def test_temp_change_heater_on_outside_tolerance(self): - """Test if temperature change doesn't turn heater on outside - tolerance. - """ + """Test if temperature change turn heater on outside tolerance.""" self._setup_switch(False) climate.set_temperature(self.hass, 30) self.hass.block_till_done() @@ -231,6 +205,30 @@ class TestClimateGenericThermostat(unittest.TestCase): self.assertEqual(SERVICE_TURN_ON, call.service) self.assertEqual(ENT_SWITCH, call.data['entity_id']) + def test_temp_change_heater_off_within_tolerance(self): + """Test if temperature change doesn't turn heater off within + tolerance. + """ + self._setup_switch(True) + climate.set_temperature(self.hass, 30) + self.hass.block_till_done() + self._setup_sensor(31) + self.hass.block_till_done() + self.assertEqual(0, len(self.calls)) + + def test_temp_change_heater_off_outside_tolerance(self): + """Test if temperature change turn heater off outside tolerance.""" + self._setup_switch(True) + climate.set_temperature(self.hass, 30) + self.hass.block_till_done() + self._setup_sensor(35) + self.hass.block_till_done() + self.assertEqual(1, len(self.calls)) + call = self.calls[0] + self.assertEqual('switch', call.domain) + self.assertEqual(SERVICE_TURN_OFF, call.service) + self.assertEqual(ENT_SWITCH, call.data['entity_id']) + def _setup_sensor(self, temp, unit=TEMP_CELSIUS): """Setup the test sensor.""" self.hass.states.set(ENT_SENSOR, temp, { @@ -297,7 +295,18 @@ class TestClimateGenericThermostatACMode(unittest.TestCase): self.assertEqual(SERVICE_TURN_ON, call.service) self.assertEqual(ENT_SWITCH, call.data['entity_id']) - def test_set_temp_change_ac_off(self): + def test_temp_change_ac_off_within_tolerance(self): + """Test if temperature change doesn't turn ac off within + tolerance. + """ + self._setup_switch(True) + climate.set_temperature(self.hass, 30) + self.hass.block_till_done() + self._setup_sensor(29.8) + self.hass.block_till_done() + self.assertEqual(0, len(self.calls)) + + def test_set_temp_change_ac_off_outside_tolerance(self): """Test if temperature change turn ac off.""" self._setup_switch(True) climate.set_temperature(self.hass, 30) @@ -310,7 +319,18 @@ class TestClimateGenericThermostatACMode(unittest.TestCase): self.assertEqual(SERVICE_TURN_OFF, call.service) self.assertEqual(ENT_SWITCH, call.data['entity_id']) - def test_temp_change_ac_on(self): + def test_temp_change_ac_on_within_tolerance(self): + """Test if temperature change doesn't turn ac on within + tolerance. + """ + self._setup_switch(False) + climate.set_temperature(self.hass, 25) + self.hass.block_till_done() + self._setup_sensor(25.2) + self.hass.block_till_done() + self.assertEqual(0, len(self.calls)) + + def test_temp_change_ac_on_outside_tolerance(self): """Test if temperature change turn ac on.""" self._setup_switch(False) climate.set_temperature(self.hass, 25) From ee5b9e72910718843af27a5023e1a022ba7ef435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Sat, 10 Dec 2016 18:53:25 +0100 Subject: [PATCH 069/141] Configurable scan options for nmap (#4838) --- .../components/device_tracker/nmap_tracker.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/device_tracker/nmap_tracker.py b/homeassistant/components/device_tracker/nmap_tracker.py index 2e8bbc5d2a1..404492e35cf 100644 --- a/homeassistant/components/device_tracker/nmap_tracker.py +++ b/homeassistant/components/device_tracker/nmap_tracker.py @@ -25,6 +25,8 @@ _LOGGER = logging.getLogger(__name__) CONF_EXCLUDE = 'exclude' # Interval in minutes to exclude devices from a scan while they are home CONF_HOME_INTERVAL = 'home_interval' +CONF_OPTIONS = 'scan_options' +DEFAULT_OPTIONS = '-F --host-timeout 5s' MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) @@ -33,7 +35,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOSTS): cv.ensure_list, vol.Required(CONF_HOME_INTERVAL, default=0): cv.positive_int, vol.Optional(CONF_EXCLUDE, default=[]): - vol.All(cv.ensure_list, vol.Length(min=1)) + vol.All(cv.ensure_list, vol.Length(min=1)), + vol.Optional(CONF_OPTIONS, default=DEFAULT_OPTIONS): + cv.string }) @@ -69,8 +73,9 @@ class NmapDeviceScanner(object): self.last_results = [] self.hosts = config[CONF_HOSTS] - self.exclude = config.get(CONF_EXCLUDE, []) + self.exclude = config[CONF_EXCLUDE] minutes = config[CONF_HOME_INTERVAL] + self._options = config[CONF_OPTIONS] self.home_interval = timedelta(minutes=minutes) self.success_init = self._update_info() @@ -103,7 +108,7 @@ class NmapDeviceScanner(object): from nmap import PortScanner, PortScannerError scanner = PortScanner() - options = '-F --host-timeout 5s ' + options = self._options if self.home_interval: boundary = dt_util.now() - self.home_interval From 7ba25f35260fe6a046c90adbf44fed711a3903dd Mon Sep 17 00:00:00 2001 From: Stefan Jonasson Date: Sun, 11 Dec 2016 09:54:50 +0100 Subject: [PATCH 070/141] Fixed crash during light objects initizilation (#4835) * Fixed crash when lights objects was inited --- homeassistant/components/light/tellstick.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/light/tellstick.py b/homeassistant/components/light/tellstick.py index 90add8f012e..d23d5e2c4d6 100644 --- a/homeassistant/components/light/tellstick.py +++ b/homeassistant/components/light/tellstick.py @@ -72,7 +72,11 @@ class TellstickLight(TellstickDevice, Light): if brightness is not None: self._brightness = brightness - self._state = (self._brightness > 0) + # _brightness is not defined when called from super + try: + self._state = (self._brightness > 0) + except AttributeError: + self._state = True else: self._state = False From cdf94646989d23023f3ddf92c1f3045e7ff8032a Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sun, 11 Dec 2016 09:05:56 +0000 Subject: [PATCH 071/141] [device_tracker.gpslogger] Add additional activity attribute. --- homeassistant/components/device_tracker/gpslogger.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/homeassistant/components/device_tracker/gpslogger.py b/homeassistant/components/device_tracker/gpslogger.py index d8e7ca8b074..22099630bd1 100644 --- a/homeassistant/components/device_tracker/gpslogger.py +++ b/homeassistant/components/device_tracker/gpslogger.py @@ -63,6 +63,7 @@ class GPSLoggerView(HomeAssistantView): accuracy = int(float(data['accuracy'])) if 'battery' in data: battery = float(data['battery']) + attrs = {} if 'speed' in data: attrs['speed'] = float(data['speed']) @@ -72,6 +73,8 @@ class GPSLoggerView(HomeAssistantView): attrs['altitude'] = float(data['altitude']) if 'provider' in data: attrs['provider'] = data['provider'] + if 'activity' in data: + attrs['activity'] = data['activity'] yield from hass.loop.run_in_executor( None, partial(self.see, dev_id=device, From e0552ad89918efd95e5ab8f2e2373c8236955b00 Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Sun, 11 Dec 2016 13:13:43 +0000 Subject: [PATCH 072/141] [device_tracker] Don't clear GPS coordinates if no GPS seen (#4848) --- homeassistant/components/device_tracker/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index d497ea4c314..ba5e28ff48f 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -426,12 +426,11 @@ class Device(Entity): if attributes: self._attributes.update(attributes) - self.gps = None - if gps is not None: try: self.gps = float(gps[0]), float(gps[1]) except (ValueError, TypeError, IndexError): + self.gps = None _LOGGER.warning('Could not parse gps value for %s: %s', self.dev_id, gps) From 46cad514d46480e3aa17f9991fa7f41f14182246 Mon Sep 17 00:00:00 2001 From: Johann Kellerman Date: Sun, 11 Dec 2016 19:18:11 +0200 Subject: [PATCH 073/141] Revert "[device_tracker] Don't clear GPS coordinates when using two device trackers." (#4851) --- homeassistant/components/device_tracker/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index ba5e28ff48f..d497ea4c314 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -426,11 +426,12 @@ class Device(Entity): if attributes: self._attributes.update(attributes) + self.gps = None + if gps is not None: try: self.gps = float(gps[0]), float(gps[1]) except (ValueError, TypeError, IndexError): - self.gps = None _LOGGER.warning('Could not parse gps value for %s: %s', self.dev_id, gps) From 99f1ea9b59edf03a1155381677002698f6cede88 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 11 Dec 2016 23:39:20 +0100 Subject: [PATCH 074/141] Migrate alarm control panel to async (#4807) * Merge alarm control panel to async * fix lint --- .../alarm_control_panel/__init__.py | 106 ++++++++++++------ .../alarm_control_panel/alarmdotcom.py | 5 - .../alarm_control_panel/concord232.py | 9 -- .../alarm_control_panel/envisalink.py | 2 +- .../components/alarm_control_panel/manual.py | 8 +- .../components/alarm_control_panel/nx584.py | 9 -- .../alarm_control_panel/simplisafe.py | 8 -- .../alarm_control_panel/verisure.py | 3 - 8 files changed, 77 insertions(+), 73 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/__init__.py b/homeassistant/components/alarm_control_panel/__init__.py index 49decfc62fe..1b64431c7a1 100644 --- a/homeassistant/components/alarm_control_panel/__init__.py +++ b/homeassistant/components/alarm_control_panel/__init__.py @@ -4,6 +4,7 @@ Component to interface with an alarm control panel. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/alarm_control_panel/ """ +import asyncio import logging import os @@ -42,40 +43,6 @@ ALARM_SERVICE_SCHEMA = vol.Schema({ }) -def setup(hass, config): - """Track states and offer events for sensors.""" - component = EntityComponent( - logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL) - - component.setup(config) - - def alarm_service_handler(service): - """Map services to methods on Alarm.""" - target_alarms = component.extract_from_service(service) - - code = service.data.get(ATTR_CODE) - - method = SERVICE_TO_METHOD[service.service] - - for alarm in target_alarms: - getattr(alarm, method)(code) - - 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')) - - for service in SERVICE_TO_METHOD: - hass.services.register(DOMAIN, service, alarm_service_handler, - descriptions.get(service), - schema=ALARM_SERVICE_SCHEMA) - return True - - def alarm_disarm(hass, code=None, entity_id=None): """Send the alarm the command for disarm.""" data = {} @@ -120,6 +87,53 @@ def alarm_trigger(hass, code=None, entity_id=None): hass.services.call(DOMAIN, SERVICE_ALARM_TRIGGER, data) +@asyncio.coroutine +def async_setup(hass, config): + """Track states and offer events for sensors.""" + component = EntityComponent( + logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL) + + yield from component.async_setup(config) + + @asyncio.coroutine + def async_alarm_service_handler(service): + """Map services to methods on Alarm.""" + target_alarms = component.async_extract_from_service(service) + + code = service.data.get(ATTR_CODE) + + method = "async_{}".format(SERVICE_TO_METHOD[service.service]) + + for alarm in target_alarms: + yield from getattr(alarm, method)(code) + + update_tasks = [] + for alarm in target_alarms: + if not alarm.should_poll: + continue + + update_coro = hass.loop.create_task( + alarm.async_update_ha_state(True)) + if hasattr(alarm, '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) + + descriptions = yield from hass.loop.run_in_executor( + None, load_yaml_config_file, os.path.join( + os.path.dirname(__file__), 'services.yaml')) + + for service in SERVICE_TO_METHOD: + hass.services.async_register( + DOMAIN, service, async_alarm_service_handler, + descriptions.get(service), schema=ALARM_SERVICE_SCHEMA) + + return True + + # pylint: disable=no-self-use class AlarmControlPanel(Entity): """An abstract class for alarm control devices.""" @@ -138,18 +152,42 @@ class AlarmControlPanel(Entity): """Send disarm command.""" raise NotImplementedError() + @asyncio.coroutine + def async_alarm_disarm(self, code=None): + """Send disarm command.""" + yield from self.hass.loop.run_in_executor( + None, self.alarm_disarm, code) + def alarm_arm_home(self, code=None): """Send arm home command.""" raise NotImplementedError() + @asyncio.coroutine + def async_alarm_arm_home(self, code=None): + """Send arm home command.""" + yield from self.hass.loop.run_in_executor( + None, self.alarm_arm_home, code) + def alarm_arm_away(self, code=None): """Send arm away command.""" raise NotImplementedError() + @asyncio.coroutine + def async_alarm_arm_away(self, code=None): + """Send arm away command.""" + yield from self.hass.loop.run_in_executor( + None, self.alarm_arm_away, code) + def alarm_trigger(self, code=None): """Send alarm trigger command.""" raise NotImplementedError() + @asyncio.coroutine + def async_alarm_trigger(self, code=None): + """Send alarm trigger command.""" + yield from self.hass.loop.run_in_executor( + None, self.alarm_trigger, code) + @property def state_attributes(self): """Return the state attributes.""" diff --git a/homeassistant/components/alarm_control_panel/alarmdotcom.py b/homeassistant/components/alarm_control_panel/alarmdotcom.py index cd37fc6a828..07f90cf4476 100644 --- a/homeassistant/components/alarm_control_panel/alarmdotcom.py +++ b/homeassistant/components/alarm_control_panel/alarmdotcom.py @@ -56,11 +56,6 @@ class AlarmDotCom(alarm.AlarmControlPanel): self._password = password self._state = STATE_UNKNOWN - @property - def should_poll(self): - """No polling needed.""" - return True - def update(self): """Fetch the latest state.""" self._state = self._alarm.state diff --git a/homeassistant/components/alarm_control_panel/concord232.py b/homeassistant/components/alarm_control_panel/concord232.py index 0bdcf274c08..de153a9e0a5 100755 --- a/homeassistant/components/alarm_control_panel/concord232.py +++ b/homeassistant/components/alarm_control_panel/concord232.py @@ -71,11 +71,6 @@ class Concord232Alarm(alarm.AlarmControlPanel): self._alarm.last_partition_update = datetime.datetime.now() self.update() - @property - def should_poll(self): - """Polling needed.""" - return True - @property def name(self): """Return the name of the device.""" @@ -126,7 +121,3 @@ class Concord232Alarm(alarm.AlarmControlPanel): def alarm_arm_away(self, code=None): """Send arm away command.""" self._alarm.arm('auto') - - def alarm_trigger(self, code=None): - """Alarm trigger command.""" - raise NotImplementedError() diff --git a/homeassistant/components/alarm_control_panel/envisalink.py b/homeassistant/components/alarm_control_panel/envisalink.py index e84320738a2..96b0fc83ea7 100644 --- a/homeassistant/components/alarm_control_panel/envisalink.py +++ b/homeassistant/components/alarm_control_panel/envisalink.py @@ -97,7 +97,7 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel): def _update_callback(self, partition): """Update HA state, if needed.""" if partition is None or int(partition) == self._partition_number: - self.hass.async_add_job(self.update_ha_state) + self.hass.async_add_job(self.async_update_ha_state()) @property def code_format(self): diff --git a/homeassistant/components/alarm_control_panel/manual.py b/homeassistant/components/alarm_control_panel/manual.py index 073d55508ed..cc67795d713 100644 --- a/homeassistant/components/alarm_control_panel/manual.py +++ b/homeassistant/components/alarm_control_panel/manual.py @@ -116,7 +116,7 @@ class ManualAlarm(alarm.AlarmControlPanel): self._state = STATE_ALARM_DISARMED self._state_ts = dt_util.utcnow() - self.update_ha_state() + self.schedule_update_ha_state() def alarm_arm_home(self, code=None): """Send arm home command.""" @@ -125,7 +125,7 @@ class ManualAlarm(alarm.AlarmControlPanel): self._state = STATE_ALARM_ARMED_HOME self._state_ts = dt_util.utcnow() - self.update_ha_state() + self.schedule_update_ha_state() if self._pending_time: track_point_in_time( @@ -139,7 +139,7 @@ class ManualAlarm(alarm.AlarmControlPanel): self._state = STATE_ALARM_ARMED_AWAY self._state_ts = dt_util.utcnow() - self.update_ha_state() + self.schedule_update_ha_state() if self._pending_time: track_point_in_time( @@ -151,7 +151,7 @@ class ManualAlarm(alarm.AlarmControlPanel): self._pre_trigger_state = self._state self._state = STATE_ALARM_TRIGGERED self._state_ts = dt_util.utcnow() - self.update_ha_state() + self.schedule_update_ha_state() if self._trigger_time: track_point_in_time( diff --git a/homeassistant/components/alarm_control_panel/nx584.py b/homeassistant/components/alarm_control_panel/nx584.py index cb32fc924e6..58ec8d915ab 100644 --- a/homeassistant/components/alarm_control_panel/nx584.py +++ b/homeassistant/components/alarm_control_panel/nx584.py @@ -62,11 +62,6 @@ class NX584Alarm(alarm.AlarmControlPanel): self._alarm.list_zones() self._state = STATE_UNKNOWN - @property - def should_poll(self): - """Polling needed.""" - return True - @property def name(self): """Return the name of the device.""" @@ -122,7 +117,3 @@ class NX584Alarm(alarm.AlarmControlPanel): def alarm_arm_away(self, code=None): """Send arm away command.""" self._alarm.arm('exit') - - def alarm_trigger(self, code=None): - """Alarm trigger command.""" - raise NotImplementedError() diff --git a/homeassistant/components/alarm_control_panel/simplisafe.py b/homeassistant/components/alarm_control_panel/simplisafe.py index 40ebfb2f39f..7a8f8409c59 100644 --- a/homeassistant/components/alarm_control_panel/simplisafe.py +++ b/homeassistant/components/alarm_control_panel/simplisafe.py @@ -61,11 +61,6 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel): else: self._state = STATE_UNKNOWN - @property - def should_poll(self): - """Poll the SimpliSafe API.""" - return True - @property def name(self): """Return the name of the device.""" @@ -104,7 +99,6 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel): return self.simplisafe.set_state('off') _LOGGER.info('SimpliSafe alarm disarming') - self.update() def alarm_arm_home(self, code=None): """Send arm home command.""" @@ -112,7 +106,6 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel): return self.simplisafe.set_state('home') _LOGGER.info('SimpliSafe alarm arming home') - self.update() def alarm_arm_away(self, code=None): """Send arm away command.""" @@ -120,7 +113,6 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel): return self.simplisafe.set_state('away') _LOGGER.info('SimpliSafe alarm arming away') - self.update() def _validate_code(self, code, state): """Validate given code.""" diff --git a/homeassistant/components/alarm_control_panel/verisure.py b/homeassistant/components/alarm_control_panel/verisure.py index 4ef07c68f59..c1a394fe462 100644 --- a/homeassistant/components/alarm_control_panel/verisure.py +++ b/homeassistant/components/alarm_control_panel/verisure.py @@ -84,18 +84,15 @@ class VerisureAlarm(alarm.AlarmControlPanel): hub.my_pages.alarm.set(code, 'DISARMED') _LOGGER.info('verisure alarm disarming') hub.my_pages.alarm.wait_while_pending() - self.update() def alarm_arm_home(self, code=None): """Send arm home command.""" hub.my_pages.alarm.set(code, 'ARMED_HOME') _LOGGER.info('verisure alarm arming home') hub.my_pages.alarm.wait_while_pending() - self.update() def alarm_arm_away(self, code=None): """Send arm away command.""" hub.my_pages.alarm.set(code, 'ARMED_AWAY') _LOGGER.info('verisure alarm arming away') hub.my_pages.alarm.wait_while_pending() - self.update() From 080c4efb000ebc0ea52f314ac4c17b3989858bc9 Mon Sep 17 00:00:00 2001 From: devdelay Date: Sun, 11 Dec 2016 17:46:10 -0500 Subject: [PATCH 075/141] Ecobee detect Smart Away (#4769) * Ecobee autoAway Event * Update ecobee.py Checking if event['running'] true is pointless because if false event['type'] will equal template and when true type will only be 'hold' or 'autoAway' so I've removed this check from the statement --- homeassistant/components/climate/ecobee.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/climate/ecobee.py b/homeassistant/components/climate/ecobee.py index c98ac6d0106..84d8c32f9ff 100644 --- a/homeassistant/components/climate/ecobee.py +++ b/homeassistant/components/climate/ecobee.py @@ -195,8 +195,9 @@ class Thermostat(ClimateDevice): mode = self.mode events = self.thermostat['events'] for event in events: - if event['running']: - mode = event['holdClimateRef'] + if event['holdClimateRef'] == 'away' or \ + event['type'] == 'autoAway': + mode = "away" break return 'away' in mode From c3923b2768b0e544579ac4fd58a4c79112054c5f Mon Sep 17 00:00:00 2001 From: Jean-Philippe Bouillot Date: Sun, 11 Dec 2016 23:47:27 +0100 Subject: [PATCH 076/141] Netatmo improving Battery info (#4724) * Improving Battery info Improving battery status info (to reflect NetAtmo API documentation and change deprecated DeviceList for WeatherStationData * Fixes from previous update Fix the hound issue. add battery_lvl, WindAngle_value, GustAngle_value, rf_status_lvl, wifi_status_lvl --- homeassistant/components/sensor/netatmo.py | 73 ++++++++++++++++++---- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/sensor/netatmo.py b/homeassistant/components/sensor/netatmo.py index c3503207d8b..20c0f94a500 100644 --- a/homeassistant/components/sensor/netatmo.py +++ b/homeassistant/components/sensor/netatmo.py @@ -38,14 +38,19 @@ SENSOR_TYPES = { 'sum_rain_1': ['sum_rain_1', 'mm', 'mdi:weather-rainy'], 'sum_rain_24': ['sum_rain_24', 'mm', 'mdi:weather-rainy'], 'battery_vp': ['Battery', '', 'mdi:battery'], + 'battery_lvl': ['Battery_lvl', '', 'mdi:battery'], 'min_temp': ['Min Temp.', TEMP_CELSIUS, 'mdi:thermometer'], 'max_temp': ['Max Temp.', TEMP_CELSIUS, 'mdi:thermometer'], 'WindAngle': ['Angle', '', 'mdi:compass'], + 'WindAngle_value': ['Angle Value', 'º', 'mdi:compass'], 'WindStrength': ['Strength', 'km/h', 'mdi:weather-windy'], 'GustAngle': ['Gust Angle', '', 'mdi:compass'], + 'GustAngle_value': ['Gust Angle Value', 'º', 'mdi:compass'], 'GustStrength': ['Gust Strength', 'km/h', 'mdi:weather-windy'], 'rf_status': ['Radio', '', 'mdi:signal'], - 'wifi_status': ['Wifi', '', 'mdi:wifi'] + 'rf_status_lvl': ['Radio_lvl', '', 'mdi:signal'], + 'wifi_status': ['Wifi', '', 'mdi:wifi'], + 'wifi_status_lvl': ['Wifi_lvl', 'dBm', 'mdi:wifi'] } MODULE_SCHEMA = vol.Schema({ @@ -103,6 +108,7 @@ class NetAtmoSensor(Entity): self._unit_of_measurement = SENSOR_TYPES[sensor_type][1] module_id = self.netatmo_data.\ station_data.moduleByName(module=module_name)['_id'] + self.module_id = module_id[1] self._unique_id = "Netatmo Sensor {0} - {1} ({2})".format(self._name, module_id, self.type) @@ -154,21 +160,58 @@ class NetAtmoSensor(Entity): self._state = data['CO2'] elif self.type == 'pressure': self._state = round(data['Pressure'], 1) - elif self.type == 'battery_vp': + elif self.type == 'battery_lvl': + self._state = data['battery_vp'] + elif self.type == 'battery_vp' and self.module_id == '6': + if data['battery_vp'] >= 5590: + self._state = "Full" + elif data['battery_vp'] >= 5180: + self._state = "High" + elif data['battery_vp'] >= 4770: + self._state = "Medium" + elif data['battery_vp'] >= 4360: + self._state = "Low" + elif data['battery_vp'] < 4360: + self._state = "Very Low" + elif self.type == 'battery_vp' and self.module_id == '5': if data['battery_vp'] >= 5500: self._state = "Full" - elif data['battery_vp'] >= 5100: + elif data['battery_vp'] >= 5000: self._state = "High" - elif data['battery_vp'] >= 4600: + elif data['battery_vp'] >= 4500: self._state = "Medium" - elif data['battery_vp'] >= 4100: + elif data['battery_vp'] >= 4000: self._state = "Low" - elif data['battery_vp'] < 4100: + elif data['battery_vp'] < 4000: + self._state = "Very Low" + elif self.type == 'battery_vp' and self.module_id == '3': + if data['battery_vp'] >= 5640: + self._state = "Full" + elif data['battery_vp'] >= 5280: + self._state = "High" + elif data['battery_vp'] >= 4920: + self._state = "Medium" + elif data['battery_vp'] >= 4560: + self._state = "Low" + elif data['battery_vp'] < 4560: + self._state = "Very Low" + elif self.type == 'battery_vp' and self.module_id == '2': + if data['battery_vp'] >= 5500: + self._state = "Full" + elif data['battery_vp'] >= 5000: + self._state = "High" + elif data['battery_vp'] >= 4500: + self._state = "Medium" + elif data['battery_vp'] >= 4000: + self._state = "Low" + elif data['battery_vp'] < 4000: self._state = "Very Low" elif self.type == 'min_temp': self._state = data['min_temp'] elif self.type == 'max_temp': self._state = data['max_temp'] + elif self.type == 'WindAngle_value': + self._state = data['WindAngle'] elif self.type == 'WindAngle': if data['WindAngle'] >= 330: self._state = "North (%d\xb0)" % data['WindAngle'] @@ -190,6 +233,8 @@ class NetAtmoSensor(Entity): self._state = "North (%d\xb0)" % data['WindAngle'] elif self.type == 'WindStrength': self._state = data['WindStrength'] + elif self.type == 'GustAngle_value': + self._state = data['GustAngle'] elif self.type == 'GustAngle': if data['GustAngle'] >= 330: self._state = "North (%d\xb0)" % data['GustAngle'] @@ -211,6 +256,8 @@ class NetAtmoSensor(Entity): self._state = "North (%d\xb0)" % data['GustAngle'] elif self.type == 'GustStrength': self._state = data['GustStrength'] + elif self.type == 'rf_status_lvl': + self._state = data['rf_status'] elif self.type == 'rf_status': if data['rf_status'] >= 90: self._state = "Low" @@ -220,13 +267,17 @@ class NetAtmoSensor(Entity): self._state = "High" elif data['rf_status'] <= 59: self._state = "Full" + elif self.type == 'wifi_status_lvl': + self._state = data['wifi_status'] elif self.type == 'wifi_status': if data['wifi_status'] >= 86: - self._state = "Bad" + self._state = "Low" elif data['wifi_status'] >= 71: - self._state = "Middle" - elif data['wifi_status'] <= 70: - self._state = "Good" + self._state = "Medium" + elif data['wifi_status'] >= 56: + self._state = "High" + elif data['wifi_status'] <= 55: + self._state = "Full" class NetAtmoData(object): @@ -248,7 +299,7 @@ class NetAtmoData(object): def update(self): """Call the Netatmo API to update the data.""" import lnetatmo - self.station_data = lnetatmo.DeviceList(self.auth) + self.station_data = lnetatmo.WeatherStationData(self.auth) if self.station is not None: self.data = self.station_data.lastData(station=self.station, From 2708e193ec95c70bc434bc7f9510cb0ed0582724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Sun, 11 Dec 2016 23:59:12 +0100 Subject: [PATCH 077/141] vlc media player (#4800) * vlc media player * Update vlc.py --- .coveragerc | 1 + homeassistant/components/media_player/vlc.py | 152 +++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 156 insertions(+) create mode 100644 homeassistant/components/media_player/vlc.py diff --git a/.coveragerc b/.coveragerc index 0d34382659b..f993482093d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -212,6 +212,7 @@ omit = homeassistant/components/media_player/snapcast.py homeassistant/components/media_player/sonos.py homeassistant/components/media_player/squeezebox.py + homeassistant/components/media_player/vlc.py homeassistant/components/media_player/yamaha.py homeassistant/components/notify/aws_lambda.py homeassistant/components/notify/aws_sns.py diff --git a/homeassistant/components/media_player/vlc.py b/homeassistant/components/media_player/vlc.py new file mode 100644 index 00000000000..ee4fef3cfde --- /dev/null +++ b/homeassistant/components/media_player/vlc.py @@ -0,0 +1,152 @@ +""" +Provide functionality to interact with vlc devices on the network. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/media_player.vlc/ +""" +import logging + +import voluptuous as vol + +from homeassistant.components.media_player import ( + SUPPORT_PAUSE, SUPPORT_PLAY_MEDIA, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, + MediaPlayerDevice, PLATFORM_SCHEMA, MEDIA_TYPE_MUSIC) +from homeassistant.const import (CONF_NAME, STATE_IDLE, STATE_PAUSED, + STATE_PLAYING) +import homeassistant.helpers.config_validation as cv +import homeassistant.util.dt as dt_util + +REQUIREMENTS = ['python-vlc==1.1.2'] + +_LOGGER = logging.getLogger(__name__) + + +SUPPORT_VLC = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \ + SUPPORT_PLAY_MEDIA + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME): cv.string, +}) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the vlc platform.""" + add_devices([VlcDevice(config.get(CONF_NAME))]) + + +class VlcDevice(MediaPlayerDevice): + """Representation of a vlc player.""" + + def __init__(self, name): + """Initialize the vlc device.""" + import vlc + self._instance = vlc.Instance() + self._vlc = self._instance.media_player_new() + self._name = name + self._volume = None + self._muted = None + self._state = None + self._media_position_updated_at = None + self._media_position = None + self._media_duration = None + + def update(self): + """Get the latest details from the device.""" + import vlc + status = self._vlc.get_state() + if status == vlc.State.Playing: + self._state = STATE_PLAYING + elif status == vlc.State.Paused: + self._state = STATE_PAUSED + else: + self._state = STATE_IDLE + self._media_duration = self._vlc.get_length()/1000 + self._media_position = self._vlc.get_position() * self._media_duration + self._media_position_updated_at = dt_util.utcnow() + + self._volume = self._vlc.audio_get_volume() / 100 + self._muted = (self._vlc.audio_get_mute() == 1) + + return True + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def state(self): + """Return the state of the device.""" + return self._state + + @property + def volume_level(self): + """Volume level of the media player (0..1).""" + return self._volume + + @property + def is_volume_muted(self): + """Boolean if volume is currently muted.""" + return self._muted + + @property + def supported_media_commands(self): + """Flag of media commands that are supported.""" + return SUPPORT_VLC + + @property + def media_content_type(self): + """Content type of current playing media.""" + return MEDIA_TYPE_MUSIC + + @property + def media_duration(self): + """Duration of current playing media in seconds.""" + return self._media_duration + + @property + def media_position(self): + """Position of current playing media in seconds.""" + return self._media_position + + @property + def media_position_updated_at(self): + """When was the position of the current playing media valid.""" + return self._media_position_updated_at + + def media_seek(self, position): + """Seek the media to a specific location.""" + track_length = self._vlc.get_length()/1000 + self._vlc.set_position(position/track_length) + + def mute_volume(self, mute): + """Mute the volume.""" + self._vlc.audio_set_mute(mute) + self._muted = mute + + def set_volume_level(self, volume): + """Set volume level, range 0..1.""" + self._vlc.audio_set_volume(int(volume * 100)) + self._volume = volume + + def media_play(self): + """Send play commmand.""" + self._vlc.play() + self._state = STATE_PLAYING + + def media_pause(self): + """Send pause command.""" + self._vlc.pause() + self._state = STATE_PAUSED + + def play_media(self, media_type, media_id, **kwargs): + """Play media from a URL or file.""" + if not media_type == MEDIA_TYPE_MUSIC: + _LOGGER.error( + "Invalid media type %s. Only %s is supported", + media_type, MEDIA_TYPE_MUSIC) + return + self._vlc.set_media(self._instance.media_new(media_id)) + self._vlc.play() + self._state = STATE_PLAYING diff --git a/requirements_all.txt b/requirements_all.txt index b67ef6f9d2b..f4e4bf6dbf3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -476,6 +476,9 @@ python-telegram-bot==5.2.0 # homeassistant.components.sensor.twitch python-twitch==1.3.0 +# homeassistant.components.media_player.vlc +python-vlc==1.1.2 + # homeassistant.components.wink python-wink==0.11.0 From 4d2480bbd19220a6a7135debceb2a25652884632 Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Sun, 11 Dec 2016 18:43:42 -0500 Subject: [PATCH 078/141] Added support to language codes on Weather Underground (#4815) * Added supported to language codes to Weather Underground * Removed unecessary None assigments --- .../components/sensor/wunderground.py | 35 ++++++++++++++++--- tests/components/sensor/test_wunderground.py | 20 ++++++----- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 3194afbe94e..2f6558cd9da 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -19,12 +19,15 @@ from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv -_RESOURCE = 'http://api.wunderground.com/api/{}/conditions/q/' -_ALERTS = 'http://api.wunderground.com/api/{}/alerts/q/' +_RESOURCE = 'http://api.wunderground.com/api/{}/conditions/{}/q/' +_ALERTS = 'http://api.wunderground.com/api/{}/alerts/{}/q/' _LOGGER = logging.getLogger(__name__) CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" CONF_PWS_ID = 'pws_id' +CONF_LANG = 'lang' + +DEFAULT_LANG = 'EN' MIN_TIME_BETWEEN_UPDATES_ALERTS = timedelta(minutes=15) MIN_TIME_BETWEEN_UPDATES_OBSERVATION = timedelta(minutes=5) @@ -80,9 +83,29 @@ ALERTS_ATTRS = [ 'message', ] +# Language Supported Codes +LANG_CODES = [ + 'AF', 'AL', 'AR', 'HY', 'AZ', 'EU', + 'BY', 'BU', 'LI', 'MY', 'CA', 'CN', + 'TW', 'CR', 'CZ', 'DK', 'DV', 'NL', + 'EN', 'EO', 'ET', 'FA', 'FI', 'FR', + 'FC', 'GZ', 'DL', 'KA', 'GR', 'GU', + 'HT', 'IL', 'HI', 'HU', 'IS', 'IO', + 'ID', 'IR', 'IT', 'JP', 'JW', 'KM', + 'KR', 'KU', 'LA', 'LV', 'LT', 'ND', + 'MK', 'MT', 'GM', 'MI', 'MR', 'MN', + 'NO', 'OC', 'PS', 'GN', 'PL', 'BR', + 'PA', 'PU', 'RO', 'RU', 'SR', 'SK', + 'SL', 'SP', 'SI', 'SW', 'CH', 'TL', + 'TT', 'TH', 'UA', 'UZ', 'VU', 'CY', + 'SN', 'JI', 'YI', +] + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_API_KEY): cv.string, vol.Optional(CONF_PWS_ID): cv.string, + vol.Optional(CONF_LANG, default=DEFAULT_LANG): + vol.All(vol.In(LANG_CODES)), vol.Required(CONF_MONITORED_CONDITIONS, default=[]): vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), }) @@ -92,7 +115,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the WUnderground sensor.""" rest = WUndergroundData(hass, config.get(CONF_API_KEY), - config.get(CONF_PWS_ID, None)) + config.get(CONF_PWS_ID), + config.get(CONF_LANG)) sensors = [] for variable in config[CONF_MONITORED_CONDITIONS]: sensors.append(WUndergroundSensor(rest, variable)) @@ -192,18 +216,19 @@ class WUndergroundSensor(Entity): class WUndergroundData(object): """Get data from WUnderground.""" - def __init__(self, hass, api_key, pws_id=None): + def __init__(self, hass, api_key, pws_id, lang): """Initialize the data object.""" self._hass = hass self._api_key = api_key self._pws_id = pws_id + self._lang = 'lang:{}'.format(lang) self._latitude = hass.config.latitude self._longitude = hass.config.longitude self.data = None self.alerts = None def _build_url(self, baseurl=_RESOURCE): - url = baseurl.format(self._api_key) + url = baseurl.format(self._api_key, self._lang) if self._pws_id: url = url + 'pws:{}'.format(self._pws_id) else: diff --git a/tests/components/sensor/test_wunderground.py b/tests/components/sensor/test_wunderground.py index 05c7fc93921..7c92ac20424 100644 --- a/tests/components/sensor/test_wunderground.py +++ b/tests/components/sensor/test_wunderground.py @@ -23,6 +23,16 @@ VALID_CONFIG = { ] } +INVALID_CONFIG = { + 'platform': 'wunderground', + 'api_key': 'BOB', + 'pws_id': 'bar', + 'lang': 'foo', + 'monitored_conditions': [ + 'weather', 'feelslike_c', 'alerts' + ] +} + FEELS_LIKE = '40' WEATHER = 'Clear' HTTPS_ICON_URL = 'https://icons.wxug.com/i/c/k/clear.gif' @@ -128,17 +138,9 @@ class TestWundergroundSetup(unittest.TestCase): self.assertTrue( wunderground.setup_platform(self.hass, VALID_CONFIG, self.add_devices, None)) - invalid_config = { - 'platform': 'wunderground', - 'api_key': 'BOB', - 'pws_id': 'bar', - 'monitored_conditions': [ - 'weather', 'feelslike_c', 'alerts' - ] - } self.assertTrue( - wunderground.setup_platform(self.hass, invalid_config, + wunderground.setup_platform(self.hass, INVALID_CONFIG, self.add_devices, None)) @unittest.mock.patch('requests.get', side_effect=mocked_requests_get) From 6edb54052f203961f11bfd7df8b6dd646d540afd Mon Sep 17 00:00:00 2001 From: IoTGuy Date: Mon, 12 Dec 2016 00:46:55 +0100 Subject: [PATCH 079/141] adding sensehat plugin (#4775) * adding sensehat plugin * added * fix PR * requirement updated * Update sensehat.py --- .coveragerc | 1 + homeassistant/components/sensor/sensehat.py | 134 ++++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 138 insertions(+) create mode 100644 homeassistant/components/sensor/sensehat.py diff --git a/.coveragerc b/.coveragerc index f993482093d..4aae4cbc242 100644 --- a/.coveragerc +++ b/.coveragerc @@ -296,6 +296,7 @@ omit = homeassistant/components/sensor/pvoutput.py homeassistant/components/sensor/sabnzbd.py homeassistant/components/sensor/scrape.py + homeassistant/components/sensor/sensehat.py homeassistant/components/sensor/serial_pm.py homeassistant/components/sensor/snmp.py homeassistant/components/sensor/sonarr.py diff --git a/homeassistant/components/sensor/sensehat.py b/homeassistant/components/sensor/sensehat.py new file mode 100644 index 00000000000..50cd233b39b --- /dev/null +++ b/homeassistant/components/sensor/sensehat.py @@ -0,0 +1,134 @@ +""" +Support for Sense HAT sensors. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/sensor.sensehat +""" +import os +import logging +from datetime import timedelta + +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import (TEMP_CELSIUS, CONF_DISPLAY_OPTIONS, CONF_NAME) +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle + +REQUIREMENTS = ['sense-hat==2.2.0'] + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_NAME = 'sensehat' + +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) + +SENSOR_TYPES = { + 'temperature': ['temperature', TEMP_CELSIUS], + 'humidity': ['humidity', "%"], + 'pressure': ['pressure', "mb"], +} + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DISPLAY_OPTIONS, default=SENSOR_TYPES): + [vol.In(SENSOR_TYPES)], + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + + +def get_cpu_temp(): + """Get CPU temperature.""" + res = os.popen("vcgencmd measure_temp").readline() + t_cpu = float(res.replace("temp=", "").replace("'C\n", "")) + return t_cpu + + +def get_average(temp_base): + """Use moving average to get better readings.""" + if not hasattr(get_average, "temp"): + get_average.temp = [temp_base, temp_base, temp_base] + get_average.temp[2] = get_average.temp[1] + get_average.temp[1] = get_average.temp[0] + get_average.temp[0] = temp_base + temp_avg = (get_average.temp[0]+get_average.temp[1]+get_average.temp[2])/3 + return temp_avg + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the sensor platform.""" + data = SenseHatData() + dev = [] + + for variable in config[CONF_DISPLAY_OPTIONS]: + dev.append(SenseHatSensor(data, variable)) + + add_devices(dev) + + +class SenseHatSensor(Entity): + """Representation of a sensehat sensor.""" + + def __init__(self, data, sensor_types): + """Initialize the sensor.""" + self.data = data + self._name = SENSOR_TYPES[sensor_types][0] + self._unit_of_measurement = SENSOR_TYPES[sensor_types][1] + self.type = sensor_types + self._state = None + """updating data.""" + self.update() + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def unit_of_measurement(self): + """Return the unit the value is expressed in.""" + return self._unit_of_measurement + + def update(self): + """Get the latest data and updates the states.""" + self.data.update() + if not self.data.humidity: + _LOGGER.error("Don't receive data!") + return + + if self.type == 'temperature': + self._state = self.data.temperature + if self.type == 'humidity': + self._state = self.data.humidity + if self.type == 'pressure': + self._state = self.data.pressure + + +class SenseHatData(object): + """Get the latest data and update.""" + + def __init__(self): + """Initialize the data object.""" + self.temperature = None + self.humidity = None + self.pressure = None + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Get the latest data from sensehat.""" + from sense_hat import SenseHat + sense = SenseHat() + temp_from_h = sense.get_temperature_from_humidity() + temp_from_p = sense.get_temperature_from_pressure() + t_cpu = get_cpu_temp() + t_total = (temp_from_h+temp_from_p)/2 + t_correct = t_total - ((t_cpu-t_total)/1.5) + t_correct = get_average(t_correct) + self.temperature = t_correct + self.humidity = sense.get_humidity() + self.pressure = sense.get_pressure() diff --git a/requirements_all.txt b/requirements_all.txt index f4e4bf6dbf3..4b2763f26bb 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -521,6 +521,9 @@ scsgate==0.1.0 # homeassistant.components.notify.sendgrid sendgrid==3.6.3 +# homeassistant.components.sensor.sensehat +sense-hat==2.2.0 + # homeassistant.components.media_player.aquostv sharp-aquos-rc==0.2 From ecc514b7e487e5dc4a9f740070c21c21d3dae04d Mon Sep 17 00:00:00 2001 From: Jeff Wilson Date: Sun, 11 Dec 2016 18:48:47 -0500 Subject: [PATCH 080/141] Use current mode to determine which temperature attributes to use (#4858) --- homeassistant/components/climate/nest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/climate/nest.py b/homeassistant/components/climate/nest.py index ab41c10e6d1..e098c3c3709 100644 --- a/homeassistant/components/climate/nest.py +++ b/homeassistant/components/climate/nest.py @@ -155,8 +155,8 @@ class NestThermostat(ClimateDevice): """Set new target temperature.""" target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW) target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH) - if target_temp_low is not None and target_temp_high is not None: - if self._mode == STATE_HEAT_COOL: + if self._mode == STATE_HEAT_COOL: + if target_temp_low is not None and target_temp_high is not None: temp = (target_temp_low, target_temp_high) else: temp = kwargs.get(ATTR_TEMPERATURE) From f4b5c439a1365ed79dc8740742c5fb4b969f3221 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Dec 2016 17:34:13 -0800 Subject: [PATCH 081/141] 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 df98d5b3c12206c858d3dd7c2943d3bad6228a39 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 11 Dec 2016 17:34:26 -0800 Subject: [PATCH 082/141] 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 48928d1f9e128b63ef7f5d96e07f4ee8bde7b422 Mon Sep 17 00:00:00 2001 From: David-Leon Pohl Date: Mon, 12 Dec 2016 02:38:33 +0100 Subject: [PATCH 083/141] Fix config validation (#4853) (#4854) --- homeassistant/components/switch/pilight.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/switch/pilight.py b/homeassistant/components/switch/pilight.py index a052848cb21..84cbbd9fb0e 100644 --- a/homeassistant/components/switch/pilight.py +++ b/homeassistant/components/switch/pilight.py @@ -35,7 +35,7 @@ COMMAND_SCHEMA = vol.Schema({ vol.Optional(CONF_ID): cv.positive_int, vol.Optional(CONF_STATE): cv.string, vol.Optional(CONF_SYSTEMCODE): cv.positive_int, -}) +}, extra=vol.ALLOW_EXTRA) SWITCHES_SCHEMA = vol.Schema({ vol.Required(CONF_ON_CODE): COMMAND_SCHEMA, From b156ae7812251c064af23e6a3548b5f0ddc08a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Arnauts?= Date: Mon, 12 Dec 2016 02:59:30 +0100 Subject: [PATCH 084/141] Add support for Hue LightGroups (#4744) * Add support for Hue LightGroup entity * Don't filter on LightGroup and add properties for a group * Reuse code from HueLight in HueLightGroup * Remove HueLightGroup and add is_group variable to HueLight * Make linter happy * Update light or lightgroup state when a new state is available * Use schedule_update_ha_state() to schedule the state update. Drop new_lightgroups and use new_lights instead. * code style fix --- homeassistant/components/light/hue.py | 66 ++++++++++++++++++++------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/homeassistant/components/light/hue.py b/homeassistant/components/light/hue.py index da2158ba78d..74247ad24ef 100644 --- a/homeassistant/components/light/hue.py +++ b/homeassistant/components/light/hue.py @@ -142,6 +142,7 @@ def setup_bridge(host, hass, add_devices, filename, allow_unreachable): configurator.request_done(request_id) lights = {} + lightgroups = {} @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update_lights(): @@ -153,9 +154,15 @@ def setup_bridge(host, hass, add_devices, filename, allow_unreachable): _LOGGER.exception("Cannot reach the bridge") return - api_states = api.get('lights') + api_lights = api.get('lights') - if not isinstance(api_states, dict): + if not isinstance(api_lights, dict): + _LOGGER.error("Got unexpected result from Hue API") + return + + api_groups = api.get('groups') + + if not isinstance(api_groups, dict): _LOGGER.error("Got unexpected result from Hue API") return @@ -167,7 +174,7 @@ def setup_bridge(host, hass, add_devices, filename, allow_unreachable): else: bridge_type = 'hue' - for light_id, info in api_states.items(): + for light_id, info in api_lights.items(): if light_id not in lights: lights[light_id] = HueLight(int(light_id), info, bridge, update_lights, @@ -175,6 +182,17 @@ def setup_bridge(host, hass, add_devices, filename, allow_unreachable): new_lights.append(lights[light_id]) else: lights[light_id].info = info + lights[light_id].schedule_update_ha_state() + + for lightgroup_id, info in api_groups.items(): + if lightgroup_id not in lightgroups: + lightgroups[lightgroup_id] = HueLight( + int(lightgroup_id), info, bridge, update_lights, + bridge_type, allow_unreachable, True) + new_lights.append(lightgroups[lightgroup_id]) + else: + lightgroups[lightgroup_id].info = info + lightgroups[lightgroup_id].schedule_update_ha_state() if new_lights: add_devices(new_lights) @@ -229,15 +247,20 @@ class HueLight(Light): """Representation of a Hue light.""" def __init__(self, light_id, info, bridge, update_lights, - bridge_type, allow_unreachable): + bridge_type, allow_unreachable, is_group=False): """Initialize the light.""" self.light_id = light_id self.info = info self.bridge = bridge self.update_lights = update_lights self.bridge_type = bridge_type - self.allow_unreachable = allow_unreachable + self.is_group = is_group + + if is_group: + self._command_func = self.bridge.set_group + else: + self._command_func = self.bridge.set_light @property def unique_id(self): @@ -247,33 +270,44 @@ class HueLight(Light): @property def name(self): - """Return the mame of the Hue light.""" + """Return the name of the Hue light.""" return self.info.get('name', DEVICE_DEFAULT_NAME) @property def brightness(self): """Return the brightness of this light between 0..255.""" - return self.info['state'].get('bri') + if self.is_group: + return self.info['action'].get('bri') + else: + return self.info['state'].get('bri') @property def xy_color(self): """Return the XY color value.""" - return self.info['state'].get('xy') + if self.is_group: + return self.info['action'].get('xy') + else: + return self.info['state'].get('xy') @property def color_temp(self): """Return the CT color value.""" - return self.info['state'].get('ct') + if self.is_group: + return self.info['action'].get('ct') + else: + return self.info['state'].get('ct') @property def is_on(self): """Return true if device is on.""" - self.update_lights() - - if self.allow_unreachable: - return self.info['state']['on'] + if self.is_group: + return self.info['state']['any_on'] else: - return self.info['state']['reachable'] and self.info['state']['on'] + if self.allow_unreachable: + return self.info['state']['on'] + else: + return self.info['state']['reachable'] and \ + self.info['state']['on'] @property def supported_features(self): @@ -322,7 +356,7 @@ class HueLight(Light): elif self.bridge_type == 'hue': command['effect'] = 'none' - self.bridge.set_light(self.light_id, command) + self._command_func(self.light_id, command) def turn_off(self, **kwargs): """Turn the specified or all lights off.""" @@ -344,7 +378,7 @@ class HueLight(Light): elif self.bridge_type == 'hue': command['alert'] = 'none' - self.bridge.set_light(self.light_id, command) + self._command_func(self.light_id, command) def update(self): """Synchronize state with bridge.""" From 04aa4e898a31e459a4f478989ea13c6d6f3efd97 Mon Sep 17 00:00:00 2001 From: Anton Lundin Date: Mon, 12 Dec 2016 06:04:36 +0100 Subject: [PATCH 085/141] Improve denon media_player (#4836) * Add debug level logging of messages in denon * Added media stop for Denon AVR Media Player * Sort source list * Rework input selection for Denon AVR This reworks the input selection, adding more modes and making it so that the media controls are only announced in modes where they actually makes sense. * Added real media info for Denon AVR Media modes * Read more configuration from denon devices This reads network name, and overrides the local name with that. This also reads the source names and reconfigures the input list to those names, and also reads the source deleted list and removes the inputs that are set to deleted in the device. * Discover and handle max volume in Denon media player * Rework source discovery in Denon media player This uses SSFUN as authorative source for which sources that we should present. --- .../components/media_player/denon.py | 113 +++++++++++++++--- 1 file changed, 95 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/media_player/denon.py b/homeassistant/components/media_player/denon.py index b167ee52808..badbae162a2 100755 --- a/homeassistant/components/media_player/denon.py +++ b/homeassistant/components/media_player/denon.py @@ -13,7 +13,7 @@ from homeassistant.components.media_player import ( PLATFORM_SCHEMA, SUPPORT_NEXT_TRACK, SUPPORT_SELECT_SOURCE, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, SUPPORT_TURN_OFF, SUPPORT_TURN_ON, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, - MediaPlayerDevice) + SUPPORT_STOP, MediaPlayerDevice) from homeassistant.const import ( CONF_HOST, CONF_NAME, STATE_OFF, STATE_ON, STATE_UNKNOWN) import homeassistant.helpers.config_validation as cv @@ -22,16 +22,32 @@ _LOGGER = logging.getLogger(__name__) DEFAULT_NAME = 'Music station' -SUPPORT_DENON = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | \ - SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | \ - SUPPORT_SELECT_SOURCE | SUPPORT_NEXT_TRACK | \ - SUPPORT_TURN_ON | SUPPORT_TURN_OFF +SUPPORT_DENON = SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE | \ + SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_SELECT_SOURCE \ + +SUPPORT_MEDIA_MODES = SUPPORT_PAUSE | SUPPORT_STOP | \ + SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) +NORMAL_INPUTS = {'Cd': 'CD', 'Dvd': 'DVD', 'Blue ray': 'BD', 'TV': 'TV', + 'Satelite / Cable': 'SAT/CBL', 'Game': 'GAME', + 'Game2': 'GAME2', 'Video Aux': 'V.AUX', 'Dock': 'DOCK'} + +MEDIA_MODES = {'Tuner': 'TUNER', 'Media server': 'SERVER', + 'Ipod dock': 'IPOD', 'Net/USB': 'NET/USB', + 'Rapsody': 'RHAPSODY', 'Napster': 'NAPSTER', + 'Pandora': 'PANDORA', 'LastFM': 'LASTFM', + 'Flickr': 'FLICKR', 'Favorites': 'FAVORITES', + 'Internet Radio': 'IRADIO', 'USB/IPOD': 'USB/IPOD'} + +# Sub-modes of 'NET/USB' +# {'USB': 'USB', 'iPod Direct': 'IPD', 'Internet Radio': 'IRP', +# 'Favorites': 'FVP'} + def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Denon platform.""" @@ -53,14 +69,39 @@ class DenonDevice(MediaPlayerDevice): self._host = host self._pwstate = 'PWSTANDBY' self._volume = 0 - self._source_list = {'TV': 'SITV', 'Tuner': 'SITUNER', - 'Internet Radio': 'SIIRP', 'Favorites': 'SIFVP'} + # Initial value 60dB, changed if we get a MVMAX + self._volume_max = 60 + self._source_list = NORMAL_INPUTS.copy() + self._source_list.update(MEDIA_MODES) self._muted = False self._mediasource = '' + self._mediainfo = '' + + self._should_setup_sources = True + + def _setup_sources(self, telnet): + # NSFRN - Network name + self._name = self.telnet_request(telnet, 'NSFRN ?')[len('NSFRN '):] + + # SSFUN - Configured sources with names + self._source_list = {} + for line in self.telnet_request(telnet, 'SSFUN ?', all_lines=True): + source, configured_name = line[len('SSFUN'):].split(" ", 1) + self._source_list[configured_name] = source + + # SSSOD - Deleted sources + for line in self.telnet_request(telnet, 'SSSOD ?', all_lines=True): + source, status = line[len('SSSOD'):].split(" ", 1) + if status == 'DEL': + for pretty_name, name in self._source_list.items(): + if source == name: + del self._source_list[pretty_name] + break @classmethod - def telnet_request(cls, telnet, command): + def telnet_request(cls, telnet, command, all_lines=False): """Execute `command` and return the response.""" + _LOGGER.debug('Sending: "%s"', command) telnet.write(command.encode('ASCII') + b'\r') lines = [] while True: @@ -68,12 +109,16 @@ class DenonDevice(MediaPlayerDevice): if not line: break lines.append(line.decode('ASCII').strip()) + _LOGGER.debug('Recived: "%s"', line) + if all_lines: + return lines return lines[0] def telnet_command(self, command): """Establish a telnet connection and sends `command`.""" telnet = telnetlib.Telnet(self._host) + _LOGGER.debug('Sending: "%s"', command) telnet.write(command.encode('ASCII') + b'\r') telnet.read_very_eager() # skip response telnet.close() @@ -85,12 +130,30 @@ class DenonDevice(MediaPlayerDevice): except OSError: return False + if self._should_setup_sources: + self._setup_sources(telnet) + self._should_setup_sources = False + self._pwstate = self.telnet_request(telnet, 'PW?') - volume_str = self.telnet_request(telnet, 'MV?')[len('MV'):] - self._volume = int(volume_str) / 60 + for line in self.telnet_request(telnet, 'MV?', all_lines=True): + if line.startswith('MVMAX '): + # only grab two digit max, don't care about any half digit + self._volume_max = int(line[len('MVMAX '):len('MVMAX XX')]) + continue + if line.startswith('MV'): + self._volume = int(line[len('MV'):]) self._muted = (self.telnet_request(telnet, 'MU?') == 'MUON') self._mediasource = self.telnet_request(telnet, 'SI?')[len('SI'):] + if self._mediasource in MEDIA_MODES.values(): + self._mediainfo = "" + answer_codes = ["NSE0", "NSE1X", "NSE2X", "NSE3X", "NSE4", "NSE5", + "NSE6", "NSE7", "NSE8"] + for line in self.telnet_request(telnet, 'NSE', all_lines=True): + self._mediainfo += line[len(answer_codes.pop()):] + '\n' + else: + self._mediainfo = self.source + telnet.close() return True @@ -112,7 +175,7 @@ class DenonDevice(MediaPlayerDevice): @property def volume_level(self): """Volume level of the media player (0..1).""" - return self._volume + return self._volume / self._volume_max @property def is_volume_muted(self): @@ -122,17 +185,27 @@ class DenonDevice(MediaPlayerDevice): @property def source_list(self): """List of available input sources.""" - return list(self._source_list.keys()) + return sorted(list(self._source_list.keys())) @property def media_title(self): - """Current media source.""" - return self._mediasource + """Current media info.""" + return self._mediainfo @property def supported_media_commands(self): """Flag of media commands that are supported.""" - return SUPPORT_DENON + if self._mediasource in MEDIA_MODES.values(): + return SUPPORT_DENON | SUPPORT_MEDIA_MODES + else: + return SUPPORT_DENON + + @property + def source(self): + """Return the current input source.""" + for pretty_name, name in self._source_list.items(): + if self._mediasource == name: + return pretty_name def turn_off(self): """Turn off media player.""" @@ -148,8 +221,8 @@ class DenonDevice(MediaPlayerDevice): def set_volume_level(self, volume): """Set volume level, range 0..1.""" - # 60dB max - self.telnet_command('MV' + str(round(volume * 60)).zfill(2)) + self.telnet_command('MV' + + str(round(volume * self._volume_max)).zfill(2)) def mute_volume(self, mute): """Mute (true) or unmute (false) media player.""" @@ -163,6 +236,10 @@ class DenonDevice(MediaPlayerDevice): """Pause media player.""" self.telnet_command('NS9B') + def media_stop(self): + """Pause media player.""" + self.telnet_command('NS9C') + def media_next_track(self): """Send the next track command.""" self.telnet_command('NS9D') @@ -177,4 +254,4 @@ class DenonDevice(MediaPlayerDevice): def select_source(self, source): """Select input source.""" - self.telnet_command(self._source_list.get(source)) + self.telnet_command('SI' + self._source_list.get(source)) From 2a7fa5afc352ffd7ba9c5542e0d7133e43b9d0f1 Mon Sep 17 00:00:00 2001 From: Erik Eriksson Date: Mon, 12 Dec 2016 06:39:37 +0100 Subject: [PATCH 086/141] Telldus Live: (#4645) - Implemented support for covers and dimmable lights. - Removed global object, use hass.data. - Disabled polling via update. - Inherit from common TelldusLiveEntity device. - Configurable polling interval - Use https API endpoint - Use tellduslive package --- homeassistant/components/cover/tellduslive.py | 46 +++ homeassistant/components/light/tellduslive.py | 59 ++++ .../components/sensor/tellduslive.py | 138 +++----- .../components/switch/tellduslive.py | 46 +-- homeassistant/components/tellduslive.py | 298 +++++++++--------- requirements_all.txt | 2 +- 6 files changed, 314 insertions(+), 275 deletions(-) create mode 100644 homeassistant/components/cover/tellduslive.py create mode 100644 homeassistant/components/light/tellduslive.py diff --git a/homeassistant/components/cover/tellduslive.py b/homeassistant/components/cover/tellduslive.py new file mode 100644 index 00000000000..c48a14e9133 --- /dev/null +++ b/homeassistant/components/cover/tellduslive.py @@ -0,0 +1,46 @@ +""" +Support for Tellstick covers using Tellstick Net. + +This platform uses the Telldus Live online service. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.tellduslive/ + +""" +import logging + +from homeassistant.components.cover import CoverDevice +from homeassistant.components.tellduslive import TelldusLiveEntity + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup covers.""" + if discovery_info is None: + return + add_devices(TelldusLiveCover(hass, cover) for cover in discovery_info) + + +class TelldusLiveCover(TelldusLiveEntity, CoverDevice): + """Representation of a cover.""" + + @property + def is_closed(self): + """Return the current position of the cover.""" + return self.device.is_down + + def close_cover(self, **kwargs): + """Close the cover.""" + self.device.down() + self.changed() + + def open_cover(self, **kwargs): + """Open the cover.""" + self.device.up() + self.changed() + + def stop_cover(self, **kwargs): + """Stop the cover.""" + self.device.stop() + self.changed() diff --git a/homeassistant/components/light/tellduslive.py b/homeassistant/components/light/tellduslive.py new file mode 100644 index 00000000000..f919268c380 --- /dev/null +++ b/homeassistant/components/light/tellduslive.py @@ -0,0 +1,59 @@ +""" +Support for Tellstick switches using Tellstick Net. + +This platform uses the Telldus Live online service. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/light.tellduslive/ + +""" +import logging + +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light) +from homeassistant.components.tellduslive import TelldusLiveEntity + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup lights.""" + if discovery_info is None: + return + add_devices(TelldusLiveLight(hass, light) for light in discovery_info) + + +class TelldusLiveLight(TelldusLiveEntity, Light): + """Representation of a light.""" + + def changed(self): + """A property of the device might have changed.""" + # pylint: disable=attribute-defined-outside-init + self._last_brightness = self.brightness + super().changed() + + @property + def brightness(self): + """Return the brightness of this light between 0..255.""" + return self.device.dim_level + + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_BRIGHTNESS + + @property + def is_on(self): + """Return true if light is on.""" + return self.device.is_on + + def turn_on(self, **kwargs): + """Turn the light on.""" + brightness = kwargs.get(ATTR_BRIGHTNESS, self._last_brightness) + self.device.dim(level=brightness) + self.changed() + + def turn_off(self, **kwargs): + """Turn the light off.""" + self.device.turn_off() + self.changed() diff --git a/homeassistant/components/sensor/tellduslive.py b/homeassistant/components/sensor/tellduslive.py index 915bbac429f..abc5843ad91 100644 --- a/homeassistant/components/sensor/tellduslive.py +++ b/homeassistant/components/sensor/tellduslive.py @@ -6,37 +6,32 @@ https://home-assistant.io/components/sensor.tellduslive/ """ import logging -from datetime import datetime -from homeassistant.components import tellduslive -from homeassistant.const import ( - ATTR_BATTERY_LEVEL, DEVICE_DEFAULT_NAME, TEMP_CELSIUS) -from homeassistant.helpers.entity import Entity - -ATTR_LAST_UPDATED = "time_last_updated" +from homeassistant.components.tellduslive import TelldusLiveEntity +from homeassistant.const import TEMP_CELSIUS _LOGGER = logging.getLogger(__name__) -SENSOR_TYPE_TEMP = "temp" -SENSOR_TYPE_HUMIDITY = "humidity" -SENSOR_TYPE_RAINRATE = "rrate" -SENSOR_TYPE_RAINTOTAL = "rtot" -SENSOR_TYPE_WINDDIRECTION = "wdir" -SENSOR_TYPE_WINDAVERAGE = "wavg" -SENSOR_TYPE_WINDGUST = "wgust" -SENSOR_TYPE_WATT = "watt" -SENSOR_TYPE_LUMINANCE = "lum" +SENSOR_TYPE_TEMP = 'temp' +SENSOR_TYPE_HUMIDITY = 'humidity' +SENSOR_TYPE_RAINRATE = 'rrate' +SENSOR_TYPE_RAINTOTAL = 'rtot' +SENSOR_TYPE_WINDDIRECTION = 'wdir' +SENSOR_TYPE_WINDAVERAGE = 'wavg' +SENSOR_TYPE_WINDGUST = 'wgust' +SENSOR_TYPE_WATT = 'watt' +SENSOR_TYPE_LUMINANCE = 'lum' SENSOR_TYPES = { - SENSOR_TYPE_TEMP: ['Temperature', TEMP_CELSIUS, "mdi:thermometer"], - SENSOR_TYPE_HUMIDITY: ['Humidity', '%', "mdi:water"], - SENSOR_TYPE_RAINRATE: ['Rain rate', 'mm', "mdi:water"], - SENSOR_TYPE_RAINTOTAL: ['Rain total', 'mm', "mdi:water"], - SENSOR_TYPE_WINDDIRECTION: ['Wind direction', '', ""], - SENSOR_TYPE_WINDAVERAGE: ['Wind average', 'm/s', ""], - SENSOR_TYPE_WINDGUST: ['Wind gust', 'm/s', ""], - SENSOR_TYPE_WATT: ['Watt', 'W', ""], - SENSOR_TYPE_LUMINANCE: ['Luminance', 'lx', ""], + SENSOR_TYPE_TEMP: ['Temperature', TEMP_CELSIUS, 'mdi:thermometer'], + SENSOR_TYPE_HUMIDITY: ['Humidity', '%', 'mdi:water'], + SENSOR_TYPE_RAINRATE: ['Rain rate', 'mm', 'mdi:water'], + SENSOR_TYPE_RAINTOTAL: ['Rain total', 'mm', 'mdi:water'], + SENSOR_TYPE_WINDDIRECTION: ['Wind direction', '', ''], + SENSOR_TYPE_WINDAVERAGE: ['Wind average', 'm/s', ''], + SENSOR_TYPE_WINDGUST: ['Wind gust', 'm/s', ''], + SENSOR_TYPE_WATT: ['Watt', 'W', ''], + SENSOR_TYPE_LUMINANCE: ['Luminance', 'lx', ''], } @@ -44,114 +39,75 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup Tellstick sensors.""" if discovery_info is None: return - add_devices(TelldusLiveSensor(sensor) for sensor in discovery_info) + add_devices(TelldusLiveSensor(hass, sensor) for sensor in discovery_info) -class TelldusLiveSensor(Entity): +class TelldusLiveSensor(TelldusLiveEntity): """Representation of a Telldus Live sensor.""" - def __init__(self, sensor_id): - """Initialize the sensor.""" - self._id = sensor_id - self.update() - _LOGGER.debug("created sensor %s", self) - - def update(self): - """Update sensor values.""" - tellduslive.NETWORK.update_sensors() - self._sensor = tellduslive.NETWORK.get_sensor(self._id) + @property + def device_id(self): + """Return id of the device.""" + return self._id[0] @property - def _sensor_name(self): - """Return the name of the sensor.""" - return self._sensor["name"] - - @property - def _sensor_value(self): - """Return the value the sensor.""" - return self._sensor["data"]["value"] - - @property - def _sensor_type(self): + def _type(self): """Return the type of the sensor.""" - return self._sensor["data"]["name"] + return self._id[1] @property - def _battery_level(self): - """Return the battery level of a sensor.""" - sensor_battery_level = self._sensor.get("battery") - return round(sensor_battery_level * 100 / 255) \ - if sensor_battery_level else None - - @property - def _last_updated(self): - """Return the last update.""" - sensor_last_updated = self._sensor.get("lastUpdated") - return str(datetime.fromtimestamp(sensor_last_updated)) \ - if sensor_last_updated else None + def _value(self): + """Return value of the sensor.""" + return self.device.value(self._id[1:]) @property def _value_as_temperature(self): """Return the value as temperature.""" - return round(float(self._sensor_value), 1) + return round(float(self._value), 1) @property def _value_as_luminance(self): """Return the value as luminance.""" - return round(float(self._sensor_value), 1) + return round(float(self._value), 1) @property def _value_as_humidity(self): """Return the value as humidity.""" - return int(round(float(self._sensor_value))) + return int(round(float(self._value))) @property def name(self): """Return the name of the sensor.""" - return "{} {}".format(self._sensor_name or DEVICE_DEFAULT_NAME, - self.quantity_name or "") - - @property - def available(self): - """Return true if the sensor is available.""" - return not self._sensor.get("offline", False) + return '{} {}'.format( + super().name, + self.quantity_name or '') @property def state(self): """Return the state of the sensor.""" - if self._sensor_type == SENSOR_TYPE_TEMP: + if self._type == SENSOR_TYPE_TEMP: return self._value_as_temperature - elif self._sensor_type == SENSOR_TYPE_HUMIDITY: + elif self._type == SENSOR_TYPE_HUMIDITY: return self._value_as_humidity - elif self._sensor_type == SENSOR_TYPE_LUMINANCE: + elif self._type == SENSOR_TYPE_LUMINANCE: return self._value_as_luminance else: - return self._sensor_value - - @property - def device_state_attributes(self): - """Return the state attributes.""" - attrs = {} - if self._battery_level is not None: - attrs[ATTR_BATTERY_LEVEL] = self._battery_level - if self._last_updated is not None: - attrs[ATTR_LAST_UPDATED] = self._last_updated - return attrs + return self._value @property def quantity_name(self): """Name of quantity.""" - return SENSOR_TYPES[self._sensor_type][0] \ - if self._sensor_type in SENSOR_TYPES else None + return SENSOR_TYPES[self._type][0] \ + if self._type in SENSOR_TYPES else None @property def unit_of_measurement(self): """Return the unit of measurement.""" - return SENSOR_TYPES[self._sensor_type][1] \ - if self._sensor_type in SENSOR_TYPES else None + return SENSOR_TYPES[self._type][1] \ + if self._type in SENSOR_TYPES else None @property def icon(self): """Return the icon.""" - return SENSOR_TYPES[self._sensor_type][2] \ - if self._sensor_type in SENSOR_TYPES else None + return SENSOR_TYPES[self._type][2] \ + if self._type in SENSOR_TYPES else None diff --git a/homeassistant/components/switch/tellduslive.py b/homeassistant/components/switch/tellduslive.py index eaa78412c27..b1450de6c5e 100644 --- a/homeassistant/components/switch/tellduslive.py +++ b/homeassistant/components/switch/tellduslive.py @@ -9,7 +9,7 @@ https://home-assistant.io/components/switch.tellduslive/ """ import logging -from homeassistant.components import tellduslive +from homeassistant.components.tellduslive import TelldusLiveEntity from homeassistant.helpers.entity import ToggleEntity _LOGGER = logging.getLogger(__name__) @@ -19,53 +19,23 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup Tellstick switches.""" if discovery_info is None: return - add_devices(TelldusLiveSwitch(switch) for switch in discovery_info) + add_devices(TelldusLiveSwitch(hass, switch) for switch in discovery_info) -class TelldusLiveSwitch(ToggleEntity): +class TelldusLiveSwitch(TelldusLiveEntity, ToggleEntity): """Representation of a Tellstick switch.""" - def __init__(self, switch_id): - """Initialize the switch.""" - self._id = switch_id - self.update() - _LOGGER.debug("created switch %s", self) - - def update(self): - """Get the latest date and update the state.""" - tellduslive.NETWORK.update_switches() - self._switch = tellduslive.NETWORK.get_switch(self._id) - - @property - def should_poll(self): - """Polling is needed.""" - return True - - @property - def assumed_state(self): - """Return true if unable to access real state of entity.""" - return True - - @property - def name(self): - """Return the name of the switch if any.""" - return self._switch["name"] - - @property - def available(self): - """Return the state of the switch.""" - return not self._switch.get("offline", False) - @property def is_on(self): """Return true if switch is on.""" - from tellive.live import const - return self._switch["state"] == const.TELLSTICK_TURNON + return self.device.is_on() def turn_on(self, **kwargs): """Turn the switch on.""" - tellduslive.NETWORK.turn_switch_on(self._id) + self.device.turn_on() + self.changed() def turn_off(self, **kwargs): """Turn the switch off.""" - tellduslive.NETWORK.turn_switch_off(self._id) + self.device.turn_off() + self.changed() diff --git a/homeassistant/components/tellduslive.py b/homeassistant/components/tellduslive.py index 36e9b01d511..cf62a28b552 100644 --- a/homeassistant/components/tellduslive.py +++ b/homeassistant/components/tellduslive.py @@ -4,18 +4,20 @@ Support for Telldus Live. For more details about this component, please refer to the documentation at https://home-assistant.io/components/tellduslive/ """ +from datetime import datetime, timedelta import logging -from datetime import timedelta - -import voluptuous as vol +from homeassistant.const import ATTR_BATTERY_LEVEL, DEVICE_DEFAULT_NAME from homeassistant.helpers import discovery -from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity import Entity +from homeassistant.helpers.event import track_point_in_utc_time +from homeassistant.util.dt import utcnow +import voluptuous as vol DOMAIN = 'tellduslive' -REQUIREMENTS = ['tellive-py==0.5.2'] +REQUIREMENTS = ['tellduslive==0.1.9'] _LOGGER = logging.getLogger(__name__) @@ -23,11 +25,10 @@ CONF_PUBLIC_KEY = 'public_key' CONF_PRIVATE_KEY = 'private_key' CONF_TOKEN = 'token' CONF_TOKEN_SECRET = 'token_secret' +CONF_UPDATE_INTERVAL = 'update_interval' -MIN_TIME_BETWEEN_SWITCH_UPDATES = timedelta(minutes=1) -MIN_TIME_BETWEEN_SENSOR_UPDATES = timedelta(minutes=5) - -NETWORK = None +MIN_UPDATE_INTERVAL = timedelta(seconds=5) +DEFAULT_UPDATE_INTERVAL = timedelta(minutes=1) CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ @@ -35,183 +36,190 @@ CONFIG_SCHEMA = vol.Schema({ vol.Required(CONF_PRIVATE_KEY): cv.string, vol.Required(CONF_TOKEN): cv.string, vol.Required(CONF_TOKEN_SECRET): cv.string, + vol.Optional(CONF_UPDATE_INTERVAL, default=DEFAULT_UPDATE_INTERVAL): ( + vol.All(cv.time_period, vol.Clamp(min=MIN_UPDATE_INTERVAL))) }), }, extra=vol.ALLOW_EXTRA) +ATTR_LAST_UPDATED = 'time_last_updated' + + def setup(hass, config): """Setup the Telldus Live component.""" - # fixme: aquire app key and provide authentication using username+password + client = TelldusLiveClient(hass, config) - global NETWORK - NETWORK = TelldusLiveData(hass, config) - - if not NETWORK.validate_session(): + if not client.validate_session(): _LOGGER.error( - "Authentication Error: " - "Please make sure you have configured your keys " - "that can be aquired from https://api.telldus.com/keys/index") + 'Authentication Error: ' + 'Please make sure you have configured your keys ' + 'that can be aquired from https://api.telldus.com/keys/index') return False - NETWORK.discover() + hass.data[DOMAIN] = client + client.update(utcnow()) return True -@Throttle(MIN_TIME_BETWEEN_SWITCH_UPDATES) -def request_switches(): - """Make request to online service.""" - _LOGGER.debug("Updating switches from Telldus Live") - switches = NETWORK.request('devices/list') - # Filter out any group of switches. - if switches and 'device' in switches: - return {switch["id"]: switch for switch in switches['device'] - if switch["type"] == "device"} - return None - - -@Throttle(MIN_TIME_BETWEEN_SENSOR_UPDATES) -def request_sensors(): - """Make request to online service.""" - _LOGGER.debug("Updating sensors from Telldus Live") - units = NETWORK.request('sensors/list') - # One unit can contain many sensors. - if units and 'sensor' in units: - return {(unit['id'], sensor['name'], sensor['scale']): - dict(unit, data=sensor) - for unit in units['sensor'] - for sensor in unit['data']} - return None - - -class TelldusLiveData(object): +class TelldusLiveClient(object): """Get the latest data and update the states.""" def __init__(self, hass, config): """Initialize the Tellus data object.""" + from tellduslive import Client + public_key = config[DOMAIN].get(CONF_PUBLIC_KEY) private_key = config[DOMAIN].get(CONF_PRIVATE_KEY) token = config[DOMAIN].get(CONF_TOKEN) token_secret = config[DOMAIN].get(CONF_TOKEN_SECRET) - from tellive.client import LiveClient - - self._switches = {} - self._sensors = {} + self.entities = [] self._hass = hass self._config = config - self._client = LiveClient( - public_key=public_key, private_key=private_key, access_token=token, - access_secret=token_secret) + self._interval = config[DOMAIN].get(CONF_UPDATE_INTERVAL) + _LOGGER.debug('Update interval %s', self._interval) + + self._client = Client(public_key, + private_key, + token, + token_secret) def validate_session(self): - """Make a dummy request to see if the session is valid.""" - response = self.request("user/profile") + """Make a request to see if the session is valid.""" + response = self._client.request_user() return response and 'email' in response - def discover(self): - """Update states, will trigger discover.""" - self.update_sensors() - self.update_switches() - - def _discover(self, found_devices, component_name): - """Send discovery event if component not yet discovered.""" - if not found_devices: - return - - _LOGGER.info("discovered %d new %s devices", - len(found_devices), component_name) - - discovery.load_platform(self._hass, component_name, DOMAIN, - found_devices, self._config) - - def request(self, what, **params): - """Send a request to the Tellstick Live API.""" - from tellive.live import const - - supported_methods = const.TELLSTICK_TURNON \ - | const.TELLSTICK_TURNOFF \ - | const.TELLSTICK_TOGGLE \ - - # Tellstick device methods not yet supported - # | const.TELLSTICK_BELL \ - # | const.TELLSTICK_DIM \ - # | const.TELLSTICK_LEARN \ - # | const.TELLSTICK_EXECUTE \ - # | const.TELLSTICK_UP \ - # | const.TELLSTICK_DOWN \ - # | const.TELLSTICK_STOP - - default_params = {'supportedMethods': supported_methods, - 'includeValues': 1, - 'includeScale': 1, - 'includeIgnored': 0} - params.update(default_params) - - # room for improvement: the telllive library doesn't seem to - # re-use sessions, instead it opens a new session for each request - # this needs to be fixed - + def update(self, now): + """Periodically poll the servers for current state.""" + _LOGGER.debug('Updating') try: - response = self._client.request(what, params) - _LOGGER.debug("got response %s", response) - return response - except OSError as error: - _LOGGER.error("failed to make request to Tellduslive servers: %s", - error) - return None + self._sync() + finally: + track_point_in_utc_time(self._hass, + self.update, + now + self._interval) - def update_devices(self, local_devices, remote_devices, component_name): - """Update local device list and discover new devices.""" - if remote_devices is None: - return local_devices + def _sync(self): + """Update local list of devices.""" + self._client.update() - remote_ids = remote_devices.keys() - local_ids = local_devices.keys() + def identify_device(device): + """Find out what type of HA component to create.""" + from tellduslive import (DIM, UP, TURNON) + if device.methods & DIM: + return 'light' + elif device.methods & UP: + return 'cover' + elif device.methods & TURNON: + return 'switch' + else: + _LOGGER.warning('Unidentified device type (methods: %d)', + device.methods) + return 'switch' - added_devices = list(remote_ids - local_ids) - self._discover(added_devices, - component_name) + def discover(device_id, component): + """Discover the component.""" + discovery.load_platform(self._hass, + component, + DOMAIN, + [device_id], + self._config) - removed_devices = list(local_ids - remote_ids) - remote_devices.update({id: dict(local_devices[id], offline=True) - for id in removed_devices}) + known_ids = set([entity.device_id for entity in self.entities]) + for device in self._client.devices: + if device.device_id in known_ids: + continue + if device.is_sensor: + for item_id in device.items: + discover((device.device_id,) + item_id, + 'sensor') + else: + discover(device.device_id, + identify_device(device)) - return remote_devices + for entity in self.entities: + entity.changed() - def update_sensors(self): - """Update local list of sensors.""" - self._sensors = self.update_devices( - self._sensors, request_sensors(), 'sensor') + def device(self, device_id): + """Return device representation.""" + import tellduslive + return tellduslive.Device(self._client, device_id) - def update_switches(self): - """Update local list of switches.""" - self._switches = self.update_devices( - self._switches, request_switches(), 'switch') + def is_available(self, device_id): + """Return device availability.""" + return device_id in self._client.device_ids - def _check_request(self, what, **params): - """Make request, check result if successful.""" - response = self.request(what, **params) - return response and response.get('status') == 'success' - def get_switch(self, switch_id): - """Return the switch representation.""" - return self._switches[switch_id] +class TelldusLiveEntity(Entity): + """Base class for all Telldus Live entities.""" - def get_sensor(self, sensor_id): - """Return the sensor representation.""" - return self._sensors[sensor_id] + def __init__(self, hass, device_id): + """Initialize the entity.""" + self._id = device_id + self._client = hass.data[DOMAIN] + self._client.entities.append(self) + _LOGGER.debug('Created device %s', self) - def turn_switch_on(self, switch_id): - """Turn switch off.""" - if self._check_request('device/turnOn', id=switch_id): - from tellive.live import const - self.get_switch(switch_id)['state'] = const.TELLSTICK_TURNON + def changed(self): + """A property of the device might have changed.""" + self.schedule_update_ha_state() - def turn_switch_off(self, switch_id): - """Turn switch on.""" - if self._check_request('device/turnOff', id=switch_id): - from tellive.live import const - self.get_switch(switch_id)['state'] = const.TELLSTICK_TURNOFF + @property + def device_id(self): + """Return the id of the device.""" + return self._id + + @property + def device(self): + """Return the representaion of the device.""" + return self._client.device(self.device_id) + + @property + def _state(self): + """Return the state of the device.""" + return self.device.state + + @property + def should_poll(self): + """Polling is not needed.""" + return False + + @property + def assumed_state(self): + """Return true if unable to access real state of entity.""" + return True + + @property + def name(self): + """Return name of device.""" + return self.device.name or DEVICE_DEFAULT_NAME + + @property + def available(self): + """Return true if device is not offline.""" + return self._client.is_available(self.device_id) + + @property + def device_state_attributes(self): + """Return the state attributes.""" + attrs = {} + if self._battery_level: + attrs[ATTR_BATTERY_LEVEL] = self._battery_level + if self._last_updated: + attrs[ATTR_LAST_UPDATED] = self._last_updated + return attrs + + @property + def _battery_level(self): + """Return the battery level of a device.""" + return round(self.device.battery * 100 / 255) \ + if self.device.battery else None + + @property + def _last_updated(self): + """Return the last update of a device.""" + return str(datetime.fromtimestamp(self.device.last_updated)) \ + if self.device.last_updated else None diff --git a/requirements_all.txt b/requirements_all.txt index 4b2763f26bb..fe37b085b2c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -560,7 +560,7 @@ steamodd==4.21 tellcore-py==1.1.2 # homeassistant.components.tellduslive -tellive-py==0.5.2 +tellduslive==0.1.9 # homeassistant.components.sensor.temper temperusb==1.5.1 From d7ccf079228565ec35dffdccd4c9eac4ce6e4588 Mon Sep 17 00:00:00 2001 From: John Mihalic Date: Mon, 12 Dec 2016 00:43:53 -0500 Subject: [PATCH 087/141] Add media position support and trailer type to Emby (#4792) * Add media position support and trailer type to Emby * Adjustments to mitigate TypeError * Simplify media_position property * Update handling when data isn't available * Update emby.py --- homeassistant/components/media_player/emby.py | 41 ++++++++++++++++--- requirements_all.txt | 2 +- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/media_player/emby.py b/homeassistant/components/media_player/emby.py index 5349e74ed40..3fae52dd052 100644 --- a/homeassistant/components/media_player/emby.py +++ b/homeassistant/components/media_player/emby.py @@ -20,12 +20,15 @@ from homeassistant.const import ( STATE_IDLE, STATE_OFF, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN) from homeassistant.helpers.event import (track_utc_time_change) from homeassistant.util import Throttle +import homeassistant.util.dt as dt_util -REQUIREMENTS = ['pyemby==0.1'] +REQUIREMENTS = ['pyemby==0.2'] MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1) +MEDIA_TYPE_TRAILER = 'trailer' + DEFAULT_PORT = 8096 _LOGGER = logging.getLogger(__name__) @@ -119,6 +122,8 @@ class EmbyClient(MediaPlayerDevice): self.update_sessions = update_sessions self.client = client self.set_device(device) + self.media_status_last_position = None + self.media_status_received = None def set_device(self, device): """Set the device property.""" @@ -178,6 +183,17 @@ class EmbyClient(MediaPlayerDevice): """Get the latest details.""" self.update_devices(no_throttle=True) self.update_sessions(no_throttle=True) + # Check if we should update progress + try: + position = self.session['PlayState']['PositionTicks'] + except (KeyError, TypeError): + self.media_status_last_position = None + self.media_status_received = None + else: + position = int(position) / 10000000 + if position != self.media_status_last_position: + self.media_status_last_position = position + self.media_status_received = dt_util.utcnow() def play_percent(self): """Return current media percent complete.""" @@ -220,6 +236,8 @@ class EmbyClient(MediaPlayerDevice): return MEDIA_TYPE_TVSHOW elif media_type == 'Movie': return MEDIA_TYPE_VIDEO + elif media_type == 'Trailer': + return MEDIA_TYPE_TRAILER return None except KeyError: return None @@ -233,19 +251,32 @@ class EmbyClient(MediaPlayerDevice): except KeyError: return None + @property + def media_position(self): + """Position of current playing media in seconds.""" + return self.media_status_last_position + + @property + def media_position_updated_at(self): + """ + When was the position of the current playing media valid. + + Returns value from homeassistant.util.dt.utcnow(). + """ + return self.media_status_received + @property def media_image_url(self): """Image url of current playing media.""" if self.now_playing_item is not None: try: return self.client.get_image( - self.now_playing_item['ThumbItemId'], 'Thumb', - self.play_percent()) + self.now_playing_item['ThumbItemId'], 'Thumb', 0) except KeyError: try: return self.client.get_image( - self.now_playing_item['PrimaryImageItemId'], 'Primary', - self.play_percent()) + self.now_playing_item[ + 'PrimaryImageItemId'], 'Primary', 0) except KeyError: return None diff --git a/requirements_all.txt b/requirements_all.txt index fe37b085b2c..f9d1b36fb5f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -390,7 +390,7 @@ pycmus==0.1.0 pydispatcher==2.0.5 # homeassistant.components.media_player.emby -pyemby==0.1 +pyemby==0.2 # homeassistant.components.envisalink pyenvisalink==1.9 From 4114884cdc91a9a238120501fe20c517475b7362 Mon Sep 17 00:00:00 2001 From: Adam Mills Date: Mon, 12 Dec 2016 00:43:59 -0500 Subject: [PATCH 088/141] Flic: Support use of queued events within timeout (#4822) * Flic: Support use of queued events within timeout * Linter fixes --- .../components/binary_sensor/flic.py | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/binary_sensor/flic.py b/homeassistant/components/binary_sensor/flic.py index 92301330605..980af069f38 100644 --- a/homeassistant/components/binary_sensor/flic.py +++ b/homeassistant/components/binary_sensor/flic.py @@ -6,7 +6,8 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.const import ( - CONF_HOST, CONF_PORT, CONF_DISCOVERY, EVENT_HOMEASSISTANT_STOP) + CONF_HOST, CONF_PORT, CONF_DISCOVERY, CONF_TIMEOUT, + EVENT_HOMEASSISTANT_STOP) from homeassistant.components.binary_sensor import ( BinarySensorDevice, PLATFORM_SCHEMA) from homeassistant.util.async import run_callback_threadsafe @@ -16,6 +17,7 @@ REQUIREMENTS = ['https://github.com/soldag/pyflic/archive/0.4.zip#pyflic==0.4'] _LOGGER = logging.getLogger(__name__) +DEFAULT_TIMEOUT = 3 CLICK_TYPE_SINGLE = "single" CLICK_TYPE_DOUBLE = "double" @@ -28,12 +30,14 @@ EVENT_NAME = "flic_click" EVENT_DATA_NAME = "button_name" EVENT_DATA_ADDRESS = "button_address" EVENT_DATA_TYPE = "click_type" +EVENT_DATA_QUEUED_TIME = "queued_time" # Validation of the user's configuration PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_HOST, default='localhost'): cv.string, vol.Optional(CONF_PORT, default=5551): cv.port, vol.Optional(CONF_DISCOVERY, default=True): cv.boolean, + vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, vol.Optional(CONF_IGNORED_CLICK_TYPES): vol.All(cv.ensure_list, [vol.In(CLICK_TYPES)]) }) @@ -102,8 +106,9 @@ def start_scanning(hass, config, async_add_entities, client): @asyncio.coroutine def async_setup_button(hass, config, async_add_entities, client, address): """Setup single button device.""" + timeout = config.get(CONF_TIMEOUT) ignored_click_types = config.get(CONF_IGNORED_CLICK_TYPES) - button = FlicButton(hass, client, address, ignored_click_types) + button = FlicButton(hass, client, address, timeout, ignored_click_types) _LOGGER.info("Connected to button (%s)", address) yield from async_add_entities([button]) @@ -127,12 +132,13 @@ def async_get_verified_addresses(client): class FlicButton(BinarySensorDevice): """Representation of a flic button.""" - def __init__(self, hass, client, address, ignored_click_types): + def __init__(self, hass, client, address, timeout, ignored_click_types): """Initialize the flic button.""" import pyflic self._hass = hass self._address = address + self._timeout = timeout self._is_down = False self._ignored_click_types = ignored_click_types or [] self._hass_click_types = { @@ -196,11 +202,27 @@ class FlicButton(BinarySensorDevice): return attr + def _queued_event_check(self, click_type, time_diff): + """Generate a log message and returns true if timeout exceeded.""" + time_string = "{:d} {}".format( + time_diff, "second" if time_diff == 1 else "seconds") + + if time_diff > self._timeout: + _LOGGER.warning( + "Queued %s dropped for %s. Time in queue was %s.", + click_type, self.address, time_string) + return True + else: + _LOGGER.info( + "Queued %s allowed for %s. Time in queue was %s.", + click_type, self.address, time_string) + return False + def _on_up_down(self, channel, click_type, was_queued, time_diff): """Update device state, if event was not queued.""" import pyflic - if was_queued: + if was_queued and self._queued_event_check(click_type, time_diff): return self._is_down = click_type == pyflic.ClickType.ButtonDown @@ -208,13 +230,19 @@ class FlicButton(BinarySensorDevice): def _on_click(self, channel, click_type, was_queued, time_diff): """Fire click event, if event was not queued.""" + # Return if click event was queued beyond allowed timeout + if was_queued and self._queued_event_check(click_type, time_diff): + return + + # Return if click event is in ignored click types hass_click_type = self._hass_click_types[click_type] - if was_queued or hass_click_type in self._ignored_click_types: + if hass_click_type in self._ignored_click_types: return self._hass.bus.fire(EVENT_NAME, { EVENT_DATA_NAME: self.name, EVENT_DATA_ADDRESS: self.address, + EVENT_DATA_QUEUED_TIME: time_diff, EVENT_DATA_TYPE: hass_click_type }) From 3467020dbf1d4747c07900d8f5fe2c1c0baf5292 Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Mon, 12 Dec 2016 00:46:19 -0500 Subject: [PATCH 089/141] Added resolution support to Amcrest cameras (#4860) * Added resolution support to Amcrest cameras * Ordered alphabetically DEFAULT_ options --- homeassistant/components/camera/amcrest.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/camera/amcrest.py b/homeassistant/components/camera/amcrest.py index 97ed45f21e4..c6568677583 100644 --- a/homeassistant/components/camera/amcrest.py +++ b/homeassistant/components/camera/amcrest.py @@ -18,16 +18,26 @@ REQUIREMENTS = ['amcrest==1.0.0'] _LOGGER = logging.getLogger(__name__) -DEFAULT_PORT = 80 +CONF_RESOLUTION = 'resolution' + DEFAULT_NAME = 'Amcrest Camera' +DEFAULT_PORT = 80 +DEFAULT_RESOLUTION = 'high' NOTIFICATION_ID = 'amcrest_notification' NOTIFICATION_TITLE = 'Amcrest Camera Setup' +RESOLUTION_LIST = { + 'high': 0, + 'low': 1, +} + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, + vol.Optional(CONF_RESOLUTION, default=DEFAULT_RESOLUTION): + vol.All(vol.In(RESOLUTION_LIST)), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, }) @@ -64,13 +74,14 @@ class AmcrestCam(Camera): def __init__(self, device_info, data): """Initialize an Amcrest camera.""" super(AmcrestCam, self).__init__() - self._name = device_info.get(CONF_NAME) self._data = data + self._name = device_info.get(CONF_NAME) + self._resolution = RESOLUTION_LIST[device_info.get(CONF_RESOLUTION)] def camera_image(self): """Return a still image reponse from the camera.""" # Send the request to snap a picture and return raw jpg data - response = self._data.camera.snapshot() + response = self._data.camera.snapshot(channel=self._resolution) return response.data @property From dbb4e4c3fac75e819d5c9dc699847c245244438b Mon Sep 17 00:00:00 2001 From: Erik Eriksson Date: Mon, 12 Dec 2016 19:05:38 +0100 Subject: [PATCH 090/141] [tellduslive] Upgrade requirement (#4865) --- homeassistant/components/tellduslive.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/tellduslive.py b/homeassistant/components/tellduslive.py index cf62a28b552..b470ae7daec 100644 --- a/homeassistant/components/tellduslive.py +++ b/homeassistant/components/tellduslive.py @@ -17,7 +17,7 @@ import voluptuous as vol DOMAIN = 'tellduslive' -REQUIREMENTS = ['tellduslive==0.1.9'] +REQUIREMENTS = ['tellduslive==0.1.13'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index f9d1b36fb5f..3e95167c1ee 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -560,7 +560,7 @@ steamodd==4.21 tellcore-py==1.1.2 # homeassistant.components.tellduslive -tellduslive==0.1.9 +tellduslive==0.1.13 # homeassistant.components.sensor.temper temperusb==1.5.1 From 12f790c7cf9548a811baae3f5cad3b9d12b4da01 Mon Sep 17 00:00:00 2001 From: Erik Eriksson Date: Tue, 13 Dec 2016 07:02:24 +0100 Subject: [PATCH 091/141] Display error message instead of exception (#4866) * Display error message instead of exception Display error message in log instead of stack trace. (Usually happens when a server is already running at the same port.) * Update __init__.py Better error handling when reading SSL certificate * Update __init__.py * Update __init__.py --- homeassistant/components/http/__init__.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py index de864a0c193..bfc5d662105 100644 --- a/homeassistant/components/http/__init__.py +++ b/homeassistant/components/http/__init__.py @@ -288,10 +288,16 @@ class HomeAssistantWSGI(object): cors_added.add(route) if self.ssl_certificate: - context = ssl.SSLContext(SSL_VERSION) - context.options |= SSL_OPTS - context.set_ciphers(CIPHERS) - context.load_cert_chain(self.ssl_certificate, self.ssl_key) + try: + context = ssl.SSLContext(SSL_VERSION) + context.options |= SSL_OPTS + context.set_ciphers(CIPHERS) + context.load_cert_chain(self.ssl_certificate, self.ssl_key) + except OSError as error: + _LOGGER.error("Could not read SSL certificate from %s: %s", + self.ssl_certificate, error) + context = None + return else: context = None @@ -305,8 +311,12 @@ class HomeAssistantWSGI(object): self._handler = self.app.make_handler() - self.server = yield from self.hass.loop.create_server( - self._handler, self.server_host, self.server_port, ssl=context) + try: + self.server = yield from self.hass.loop.create_server( + self._handler, self.server_host, self.server_port, ssl=context) + except OSError as error: + _LOGGER.error("Failed to create HTTP server at port %d: %s", + self.server_port, error) self.app._frozen = False # pylint: disable=protected-access From eeb8bc391377c4f8a0422d3b2dc56f2ac420dad0 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 12 Dec 2016 22:18:20 -0800 Subject: [PATCH 092/141] Fix dev tag detection in release script (#4873) --- script/release | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/script/release b/script/release index 40d906b17bf..43af9b92cb1 100755 --- a/script/release +++ b/script/release @@ -2,7 +2,15 @@ cd "$(dirname "$0")/.." -head -n 3 homeassistant/const.py | tail -n 1 | grep dev +head -n 5 homeassistant/const.py | tail -n 1 | grep PATCH_VERSION > /dev/null + +if [ $? -eq 1 ] +then + echo "Patch version not found on const.py line 5" + exit 1 +fi + +head -n 5 homeassistant/const.py | tail -n 1 | grep dev > /dev/null if [ $? -eq 0 ] then From acb841a1f4bf2507bbec4826ec5516e9c8c47d9c Mon Sep 17 00:00:00 2001 From: John Mihalic Date: Tue, 13 Dec 2016 02:10:16 -0500 Subject: [PATCH 093/141] Add Hikvision binary sensor component (#4825) * Add Hikvision binary sensor component * Simplify customize configuration * Add delay attribute * Remove use of threading timer, fix delay functionality --- .coveragerc | 1 + .../components/binary_sensor/hikvision.py | 262 ++++++++++++++++++ requirements_all.txt | 4 + 3 files changed, 267 insertions(+) create mode 100644 homeassistant/components/binary_sensor/hikvision.py diff --git a/.coveragerc b/.coveragerc index 4aae4cbc242..3168a20bd8c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -123,6 +123,7 @@ omit = homeassistant/components/binary_sensor/arest.py homeassistant/components/binary_sensor/concord232.py homeassistant/components/binary_sensor/flic.py + homeassistant/components/binary_sensor/hikvision.py homeassistant/components/binary_sensor/rest.py homeassistant/components/browser.py homeassistant/components/camera/amcrest.py diff --git a/homeassistant/components/binary_sensor/hikvision.py b/homeassistant/components/binary_sensor/hikvision.py new file mode 100644 index 00000000000..90d61cbf3b7 --- /dev/null +++ b/homeassistant/components/binary_sensor/hikvision.py @@ -0,0 +1,262 @@ +""" +Support for Hikvision event stream events represented as binary sensors. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/binary_sensor.hikvision/ +""" +import logging +from datetime import timedelta +import voluptuous as vol + +from homeassistant.helpers.event import track_point_in_utc_time +from homeassistant.util.dt import utcnow +from homeassistant.components.binary_sensor import ( + BinarySensorDevice, PLATFORM_SCHEMA) +import homeassistant.helpers.config_validation as cv +from homeassistant.const import ( + CONF_HOST, CONF_PORT, CONF_NAME, CONF_USERNAME, CONF_PASSWORD, + CONF_SSL, EVENT_HOMEASSISTANT_STOP, ATTR_LAST_TRIP_TIME, CONF_CUSTOMIZE) + +REQUIREMENTS = ['pyhik==0.0.6', 'pydispatcher==2.0.5'] +_LOGGER = logging.getLogger(__name__) + +CONF_IGNORED = 'ignored' +CONF_DELAY = 'delay' + +DEFAULT_PORT = 80 +DEFAULT_IGNORED = False +DEFAULT_DELAY = 0 + +ATTR_DELAY = 'delay' + +SENSOR_CLASS_MAP = { + 'Motion': 'motion', + 'Line Crossing': 'motion', + 'IO Trigger': None, + 'Field Detection': 'motion', + 'Video Loss': None, + 'Tamper Detection': 'motion', + 'Shelter Alarm': None, + 'Disk Full': None, + 'Disk Error': None, + 'Net Interface Broken': 'connectivity', + 'IP Conflict': 'connectivity', + 'Illegal Access': None, + 'Video Mismatch': None, + 'Bad Video': None, + 'PIR Alarm': 'motion', + 'Face Detection': 'motion', +} + +CUSTOMIZE_SCHEMA = vol.Schema({ + vol.Optional(CONF_IGNORED, default=DEFAULT_IGNORED): cv.boolean, + vol.Optional(CONF_DELAY, default=DEFAULT_DELAY): cv.positive_int + }) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=None): cv.string, + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_SSL, default=False): cv.boolean, + vol.Required(CONF_USERNAME): cv.string, + vol.Required(CONF_PASSWORD): cv.string, + vol.Optional(CONF_CUSTOMIZE, default={}): + vol.Schema({cv.string: CUSTOMIZE_SCHEMA}), +}) + + +def setup_platform(hass, config, add_entities, discovery_info=None): + """Setup Hikvision binary sensor devices.""" + name = config.get(CONF_NAME) + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + username = config.get(CONF_USERNAME) + password = config.get(CONF_PASSWORD) + + customize = config.get(CONF_CUSTOMIZE) + + if config.get(CONF_SSL): + protocol = "https" + else: + protocol = "http" + + url = '{}://{}'.format(protocol, host) + + data = HikvisionData(hass, url, port, name, username, password) + + if data.sensors is None: + _LOGGER.error('Hikvision event stream has no data, unable to setup.') + return False + + entities = [] + + for sensor in data.sensors: + # Build sensor name, then parse customize config. + sensor_name = sensor.replace(' ', '_') + + custom = customize.get(sensor_name.lower(), {}) + ignore = custom.get(CONF_IGNORED) + delay = custom.get(CONF_DELAY) + + _LOGGER.debug('Entity: %s - %s, Options - Ignore: %s, Delay: %s', + data.name, sensor_name, ignore, delay) + if not ignore: + entities.append(HikvisionBinarySensor(hass, sensor, data, delay)) + + add_entities(entities) + + +class HikvisionData(object): + """Hikvision camera event stream object.""" + + def __init__(self, hass, url, port, name, username, password): + """Initialize the data oject.""" + from pyhik.hikvision import HikCamera + self._url = url + self._port = port + self._name = name + self._username = username + self._password = password + + # Establish camera + self._cam = HikCamera(self._url, self._port, + self._username, self._password) + + if self._name is None: + self._name = self._cam.get_name + + # Start event stream + self._cam.start_stream() + + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self.stop_hik) + + def stop_hik(self, event): + """Shutdown Hikvision subscriptions and subscription thread on exit.""" + self._cam.disconnect() + + @property + def sensors(self): + """Return list of available sensors and their states.""" + return self._cam.current_event_states + + @property + def cam_id(self): + """Return camera id.""" + return self._cam.get_id + + @property + def name(self): + """Return camera name.""" + return self._name + + +class HikvisionBinarySensor(BinarySensorDevice): + """Representation of a Hikvision binary sensor.""" + + def __init__(self, hass, sensor, cam, delay): + """Initialize the binary_sensor.""" + from pydispatch import dispatcher + + self._hass = hass + self._cam = cam + self._name = self._cam.name + ' ' + sensor + self._id = self._cam.cam_id + '.' + sensor + self._sensor = sensor + + if delay is None: + self._delay = 0 + else: + self._delay = delay + + self._timer = None + + # Form signal for dispatcher + signal = 'ValueChanged.{}'.format(self._cam.cam_id) + + dispatcher.connect(self._update_callback, + signal=signal, + sender=self._sensor) + + def _sensor_state(self): + """Extract sensor state.""" + return self._cam.sensors[self._sensor][0] + + def _sensor_last_update(self): + """Extract sensor last update time.""" + return self._cam.sensors[self._sensor][3] + + @property + def name(self): + """Return the name of the Hikvision sensor.""" + return self._name + + @property + def unique_id(self): + """Return an unique ID.""" + return '{}.{}'.format(self.__class__, self._id) + + @property + def is_on(self): + """Return true if sensor is on.""" + return self._sensor_state() + + @property + def sensor_class(self): + """Return the class of this sensor, from SENSOR_CLASSES.""" + try: + return SENSOR_CLASS_MAP[self._sensor] + except KeyError: + # Sensor must be unknown to us, add as generic + return None + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def device_state_attributes(self): + """Return the state attributes.""" + attr = {} + attr[ATTR_LAST_TRIP_TIME] = self._sensor_last_update() + + if self._delay != 0: + attr[ATTR_DELAY] = self._delay + + return attr + + def _update_callback(self, signal, sender): + """Update the sensor's state, if needed.""" + _LOGGER.debug('Dispatcher callback, signal: %s, sender: %s', + signal, sender) + + if sender is not self._sensor: + return + + if self._delay > 0 and not self.is_on: + # Set timer to wait until updating the state + def _delay_update(now): + """Timer callback for sensor update.""" + _LOGGER.debug('%s Called delayed (%ssec) update.', + self._name, self._delay) + self.schedule_update_ha_state() + self._timer = None + + if self._timer is not None: + self._timer() + self._timer = None + + self._timer = track_point_in_utc_time( + self._hass, _delay_update, + utcnow() + timedelta(seconds=self._delay)) + + elif self._delay > 0 and self.is_on: + # For delayed sensors kill any callbacks on true events and update + if self._timer is not None: + self._timer() + self._timer = None + + self.schedule_update_ha_state() + + else: + self.schedule_update_ha_state() diff --git a/requirements_all.txt b/requirements_all.txt index 3e95167c1ee..799b2b29b11 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -387,6 +387,7 @@ pycmus==0.1.0 # homeassistant.components.envisalink # homeassistant.components.zwave +# homeassistant.components.binary_sensor.hikvision pydispatcher==2.0.5 # homeassistant.components.media_player.emby @@ -401,6 +402,9 @@ pyfttt==0.3 # homeassistant.components.remote.harmony pyharmony==1.0.12 +# homeassistant.components.binary_sensor.hikvision +pyhik==0.0.6 + # homeassistant.components.homematic pyhomematic==0.1.18 From 2dec38d8d4f2461448fc05de352e619bc09167dd Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 13 Dec 2016 08:23:08 +0100 Subject: [PATCH 094/141] TTS Component / Google speech platform (#4837) * TTS Component / Google speech platform * Change file backend handling / cache * Use mimetype / rename Provider function / allow cache on service call * Add a memcache for faster response * Add demo platform * First version of unittest * Address comments * improve error handling / address comments * Add google unittest & check http response code * Change url param handling * add test for other language * Change hash to sha256 for same hash on every os/hardware * add unittest for receive demo data * add test for error cases * Test case load from file to mem over aiohttp server * Use cache SpeechManager level, address other comments * Add service for clear cache * Update service.yaml * add support for spliting google message --- .../components/media_player/__init__.py | 2 +- homeassistant/components/tts/__init__.py | 421 ++++++++++++++++++ homeassistant/components/tts/demo.mp3 | Bin 0 -> 8256 bytes homeassistant/components/tts/demo.py | 29 ++ homeassistant/components/tts/google.py | 117 +++++ homeassistant/components/tts/services.yaml | 14 + requirements_all.txt | 3 + tests/components/tts/__init__.py | 1 + tests/components/tts/test_google.py | 199 +++++++++ tests/components/tts/test_init.py | 320 +++++++++++++ tests/test_util/aiohttp.py | 9 +- 11 files changed, 1110 insertions(+), 5 deletions(-) create mode 100644 homeassistant/components/tts/__init__.py create mode 100644 homeassistant/components/tts/demo.mp3 create mode 100644 homeassistant/components/tts/demo.py create mode 100644 homeassistant/components/tts/google.py create mode 100644 homeassistant/components/tts/services.yaml create mode 100644 tests/components/tts/__init__.py create mode 100644 tests/components/tts/test_google.py create mode 100644 tests/components/tts/test_init.py diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index fa2ecee4337..3dea75df874 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -162,7 +162,7 @@ MEDIA_PLAYER_MEDIA_SEEK_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({ MEDIA_PLAYER_PLAY_MEDIA_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({ vol.Required(ATTR_MEDIA_CONTENT_TYPE): cv.string, vol.Required(ATTR_MEDIA_CONTENT_ID): cv.string, - ATTR_MEDIA_ENQUEUE: cv.boolean, + vol.Optional(ATTR_MEDIA_ENQUEUE): cv.boolean, }) MEDIA_PLAYER_SELECT_SOURCE_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({ diff --git a/homeassistant/components/tts/__init__.py b/homeassistant/components/tts/__init__.py new file mode 100644 index 00000000000..0e75de88cc5 --- /dev/null +++ b/homeassistant/components/tts/__init__.py @@ -0,0 +1,421 @@ +""" +Provide functionality to TTS. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/tts/ +""" +import asyncio +import logging +import hashlib +import mimetypes +import os +import re + +from aiohttp import web +import voluptuous as vol + +from homeassistant.const import ATTR_ENTITY_ID +from homeassistant.bootstrap import async_prepare_setup_platform +from homeassistant.core import callback +from homeassistant.config import load_yaml_config_file +from homeassistant.components.http import HomeAssistantView +from homeassistant.components.media_player import ( + SERVICE_PLAY_MEDIA, MEDIA_TYPE_MUSIC, ATTR_MEDIA_CONTENT_ID, + ATTR_MEDIA_CONTENT_TYPE, DOMAIN as DOMAIN_MP) +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers import config_per_platform +import homeassistant.helpers.config_validation as cv + +DOMAIN = 'tts' +DEPENDENCIES = ['http'] + +_LOGGER = logging.getLogger(__name__) + +MEM_CACHE_FILENAME = 'filename' +MEM_CACHE_VOICE = 'voice' + +CONF_LANG = 'language' +CONF_CACHE = 'cache' +CONF_CACHE_DIR = 'cache_dir' +CONF_TIME_MEMORY = 'time_memory' + +DEFAULT_CACHE = True +DEFAULT_CACHE_DIR = "tts" +DEFAULT_LANG = 'en' +DEFAULT_TIME_MEMORY = 300 + +SERVICE_SAY = 'say' +SERVICE_CLEAR_CACHE = 'clear_cache' + +ATTR_MESSAGE = 'message' +ATTR_CACHE = 'cache' + +_RE_VOICE_FILE = re.compile(r"([a-f0-9]{40})_([a-z]+)\.[a-z0-9]{3,4}") + +PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_LANG, default=DEFAULT_LANG): cv.string, + vol.Optional(CONF_CACHE, default=DEFAULT_CACHE): cv.boolean, + vol.Optional(CONF_CACHE_DIR, default=DEFAULT_CACHE_DIR): cv.string, + vol.Optional(CONF_TIME_MEMORY, default=DEFAULT_TIME_MEMORY): + vol.All(vol.Coerce(int), vol.Range(min=60, max=57600)), +}) + + +SCHEMA_SERVICE_SAY = vol.Schema({ + vol.Required(ATTR_MESSAGE): cv.string, + vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, + vol.Optional(ATTR_CACHE): cv.boolean, +}) + +SCHEMA_SERVICE_CLEAR_CACHE = vol.Schema({}) + + +@asyncio.coroutine +def async_setup(hass, config): + """Setup TTS.""" + tts = SpeechManager(hass) + + try: + conf = config[DOMAIN][0] if len(config.get(DOMAIN, [])) > 0 else {} + use_cache = conf.get(CONF_CACHE, DEFAULT_CACHE) + cache_dir = conf.get(CONF_CACHE_DIR, DEFAULT_CACHE_DIR) + time_memory = conf.get(CONF_TIME_MEMORY, DEFAULT_LANG) + + yield from tts.async_init_cache(use_cache, cache_dir, time_memory) + except (HomeAssistantError, KeyError) as err: + _LOGGER.error("Error on cache init %s", err) + return False + + hass.http.register_view(TextToSpeechView(tts)) + + descriptions = yield from hass.loop.run_in_executor( + None, load_yaml_config_file, + os.path.join(os.path.dirname(__file__), 'services.yaml')) + + @asyncio.coroutine + def async_setup_platform(p_type, p_config, disc_info=None): + """Setup a tts platform.""" + platform = yield from async_prepare_setup_platform( + hass, config, DOMAIN, p_type) + if platform is None: + return + + try: + if hasattr(platform, 'async_get_engine'): + provider = yield from platform.async_get_engine( + hass, p_config) + else: + provider = yield from hass.loop.run_in_executor( + None, platform.get_engine, hass, p_config) + + if provider is None: + _LOGGER.error('Error setting up platform %s', p_type) + return + + tts.async_register_engine(p_type, provider, p_config) + except Exception: # pylint: disable=broad-except + _LOGGER.exception('Error setting up platform %s', p_type) + return + + @asyncio.coroutine + def async_say_handle(service): + """Service handle for say.""" + entity_ids = service.data.get(ATTR_ENTITY_ID) + message = service.data.get(ATTR_MESSAGE) + cache = service.data.get(ATTR_CACHE) + + try: + url = yield from tts.async_get_url( + p_type, message, cache=cache) + except HomeAssistantError as err: + _LOGGER.error("Error on init tts: %s", err) + return + + data = { + ATTR_MEDIA_CONTENT_ID: url, + ATTR_MEDIA_CONTENT_TYPE: MEDIA_TYPE_MUSIC, + } + + if entity_ids: + data[ATTR_ENTITY_ID] = entity_ids + + yield from hass.services.async_call( + DOMAIN_MP, SERVICE_PLAY_MEDIA, data, blocking=True) + + hass.services.async_register( + DOMAIN, "{}_{}".format(p_type, SERVICE_SAY), async_say_handle, + descriptions.get(SERVICE_SAY), schema=SCHEMA_SERVICE_SAY) + + setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config + in config_per_platform(config, DOMAIN)] + + if setup_tasks: + yield from asyncio.wait(setup_tasks, loop=hass.loop) + + @asyncio.coroutine + def async_clear_cache_handle(service): + """Handle clear cache service call.""" + yield from tts.async_clear_cache() + + hass.services.async_register( + DOMAIN, SERVICE_CLEAR_CACHE, async_clear_cache_handle, + descriptions.get(SERVICE_CLEAR_CACHE), schema=SERVICE_CLEAR_CACHE) + + return True + + +class SpeechManager(object): + """Representation of a speech store.""" + + def __init__(self, hass): + """Initialize a speech store.""" + self.hass = hass + self.providers = {} + + self.use_cache = True + self.cache_dir = None + self.time_memory = None + self.file_cache = {} + self.mem_cache = {} + + @asyncio.coroutine + def async_init_cache(self, use_cache, cache_dir, time_memory): + """Init config folder and load file cache.""" + self.use_cache = use_cache + self.time_memory = time_memory + + def init_tts_cache_dir(cache_dir): + """Init cache folder.""" + if not os.path.isabs(cache_dir): + cache_dir = self.hass.config.path(cache_dir) + if not os.path.isdir(cache_dir): + _LOGGER.info("Create cache dir %s.", cache_dir) + os.mkdir(cache_dir) + return cache_dir + + try: + self.cache_dir = yield from self.hass.loop.run_in_executor( + None, init_tts_cache_dir, cache_dir) + except OSError as err: + raise HomeAssistantError( + "Can't init cache dir {}".format(err)) + + def get_cache_files(): + """Return a dict of given engine files.""" + cache = {} + + folder_data = os.listdir(self.cache_dir) + for file_data in folder_data: + record = _RE_VOICE_FILE.match(file_data) + if record: + key = "{}_{}".format(record.group(1), record.group(2)) + cache[key.lower()] = file_data.lower() + return cache + + try: + cache_files = yield from self.hass.loop.run_in_executor( + None, get_cache_files) + except OSError as err: + raise HomeAssistantError( + "Can't read cache dir {}".format(err)) + + if cache_files: + self.file_cache.update(cache_files) + + @asyncio.coroutine + def async_clear_cache(self): + """Read file cache and delete files.""" + self.mem_cache = {} + + def remove_files(): + """Remove files from filesystem.""" + for _, filename in self.file_cache.items(): + try: + os.remove(os.path.join(self.cache_dir), filename) + except OSError: + pass + + yield from self.hass.loop.run_in_executor(None, remove_files) + self.file_cache = {} + + @callback + def async_register_engine(self, engine, provider, config): + """Register a TTS provider.""" + provider.hass = self.hass + provider.language = config.get(CONF_LANG) + self.providers[engine] = provider + + @asyncio.coroutine + def async_get_url(self, engine, message, cache=None): + """Get URL for play message. + + This method is a coroutine. + """ + msg_hash = hashlib.sha1(bytes(message, 'utf-8')).hexdigest() + key = ("{}_{}".format(msg_hash, engine)).lower() + use_cache = cache if cache is not None else self.use_cache + + # is speech allready in memory + if key in self.mem_cache: + filename = self.mem_cache[key][MEM_CACHE_FILENAME] + # is file store in file cache + elif use_cache and key in self.file_cache: + filename = self.file_cache[key] + self.hass.async_add_job(self.async_file_to_mem(engine, key)) + # load speech from provider into memory + else: + filename = yield from self.async_get_tts_audio( + engine, key, message, use_cache) + + return "{}/api/tts_proxy/{}".format( + self.hass.config.api.base_url, filename) + + @asyncio.coroutine + def async_get_tts_audio(self, engine, key, message, cache): + """Receive TTS and store for view in cache. + + This method is a coroutine. + """ + provider = self.providers[engine] + extension, data = yield from provider.async_get_tts_audio(message) + + if data is None or extension is None: + raise HomeAssistantError( + "No TTS from {} for '{}'".format(engine, message)) + + # create file infos + filename = ("{}.{}".format(key, extension)).lower() + + # save to memory + self._async_store_to_memcache(key, filename, data) + + if cache: + self.hass.async_add_job( + self.async_save_tts_audio(key, filename, data)) + + return filename + + @asyncio.coroutine + def async_save_tts_audio(self, key, filename, data): + """Store voice data to file and file_cache. + + This method is a coroutine. + """ + voice_file = os.path.join(self.cache_dir, filename) + + def save_speech(): + """Store speech to filesystem.""" + with open(voice_file, 'wb') as speech: + speech.write(data) + + try: + yield from self.hass.loop.run_in_executor(None, save_speech) + self.file_cache[key] = filename + except OSError: + _LOGGER.error("Can't write %s", filename) + + @asyncio.coroutine + def async_file_to_mem(self, engine, key): + """Load voice from file cache into memory. + + This method is a coroutine. + """ + filename = self.file_cache.get(key) + if not filename: + raise HomeAssistantError("Key {} not in file cache!".format(key)) + + voice_file = os.path.join(self.cache_dir, filename) + + def load_speech(): + """Load a speech from filesystem.""" + with open(voice_file, 'rb') as speech: + return speech.read() + + try: + data = yield from self.hass.loop.run_in_executor(None, load_speech) + except OSError: + raise HomeAssistantError("Can't read {}".format(voice_file)) + + self._async_store_to_memcache(key, filename, data) + + @callback + def _async_store_to_memcache(self, key, filename, data): + """Store data to memcache and set timer to remove it.""" + self.mem_cache[key] = { + MEM_CACHE_FILENAME: filename, + MEM_CACHE_VOICE: data, + } + + @callback + def async_remove_from_mem(): + """Cleanup memcache.""" + self.mem_cache.pop(key) + + self.hass.loop.call_later(self.time_memory, async_remove_from_mem) + + @asyncio.coroutine + def async_read_tts(self, filename): + """Read a voice file and return binary. + + This method is a coroutine. + """ + record = _RE_VOICE_FILE.match(filename.lower()) + if not record: + raise HomeAssistantError("Wrong tts file format!") + + key = "{}_{}".format(record.group(1), record.group(2)) + + if key not in self.mem_cache: + if key not in self.file_cache: + raise HomeAssistantError("%s not in cache!", key) + engine = record.group(2) + yield from self.async_file_to_mem(engine, key) + + content, _ = mimetypes.guess_type(filename) + return (content, self.mem_cache[key][MEM_CACHE_VOICE]) + + +class Provider(object): + """Represent a single provider.""" + + hass = None + language = DEFAULT_LANG + + def get_tts_audio(self, message): + """Load tts audio file from provider.""" + raise NotImplementedError() + + @asyncio.coroutine + def async_get_tts_audio(self, message): + """Load tts audio file from provider. + + Return a tuple of file extension and data as bytes. + + This method is a coroutine. + """ + extension, data = yield from self.hass.loop.run_in_executor( + None, self.get_tts_audio, message) + return (extension, data) + + +class TextToSpeechView(HomeAssistantView): + """TTS view to serve an speech audio.""" + + requires_auth = False + url = "/api/tts_proxy/{filename}" + name = "api:tts:speech" + + def __init__(self, tts): + """Initialize a tts view.""" + self.tts = tts + + @asyncio.coroutine + def get(self, request, filename): + """Start a get request.""" + try: + content, data = yield from self.tts.async_read_tts(filename) + except HomeAssistantError as err: + _LOGGER.error("Error on load tts: %s", err) + return web.Response(status=404) + + return web.Response(body=data, content_type=content) diff --git a/homeassistant/components/tts/demo.mp3 b/homeassistant/components/tts/demo.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..f34241c769856718331a5e523f7d9b8b026a2c30 GIT binary patch literal 8256 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 literal 0 HcmV?d00001 diff --git a/homeassistant/components/tts/demo.py b/homeassistant/components/tts/demo.py new file mode 100644 index 00000000000..a63bd6373ea --- /dev/null +++ b/homeassistant/components/tts/demo.py @@ -0,0 +1,29 @@ +""" +Support for the demo speech service. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/demo/ +""" +import os + +from homeassistant.components.tts import Provider + + +def get_engine(hass, config): + """Setup Demo speech component.""" + return DemoProvider() + + +class DemoProvider(Provider): + """Demo speech api provider.""" + + def get_tts_audio(self, message): + """Load TTS from demo.""" + filename = os.path.join(os.path.dirname(__file__), "demo.mp3") + try: + with open(filename, 'rb') as voice: + data = voice.read() + except OSError: + return + + return ("mp3", data) diff --git a/homeassistant/components/tts/google.py b/homeassistant/components/tts/google.py new file mode 100644 index 00000000000..b271b2468d1 --- /dev/null +++ b/homeassistant/components/tts/google.py @@ -0,0 +1,117 @@ +""" +Support for the google speech service. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/tts/google/ +""" +import asyncio +import logging +import re + +import aiohttp +import async_timeout +import yarl + +from homeassistant.components.tts import Provider +from homeassistant.helpers.aiohttp_client import async_get_clientsession + +REQUIREMENTS = ["gTTS-token==1.1.1"] + +_LOGGER = logging.getLogger(__name__) + +GOOGLE_SPEECH_URL = "http://translate.google.com/translate_tts" +MESSAGE_SIZE = 148 + + +@asyncio.coroutine +def async_get_engine(hass, config): + """Setup Google speech component.""" + return GoogleProvider(hass) + + +class GoogleProvider(Provider): + """Google speech api provider.""" + + def __init__(self, hass): + """Init Google TTS service.""" + self.hass = hass + self.headers = { + 'Referer': "http://translate.google.com/", + 'User-Agent': ("Mozilla/5.0 (Windows NT 10.0; WOW64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/47.0.2526.106 Safari/537.36") + } + + @asyncio.coroutine + def async_get_tts_audio(self, message): + """Load TTS from google.""" + from gtts_token import gtts_token + + token = gtts_token.Token() + websession = async_get_clientsession(self.hass) + message_parts = self._split_message_to_parts(message) + + data = b'' + for idx, part in enumerate(message_parts): + part_token = yield from self.hass.loop.run_in_executor( + None, token.calculate_token, part) + + url_param = { + 'ie': 'UTF-8', + 'tl': self.language, + 'q': yarl.quote(part), + 'tk': part_token, + 'total': len(message_parts), + 'idx': idx, + 'client': 'tw-ob', + 'textlen': len(part), + } + + request = None + try: + with async_timeout.timeout(10, loop=self.hass.loop): + request = yield from websession.get( + GOOGLE_SPEECH_URL, params=url_param, + headers=self.headers + ) + + if request.status != 200: + _LOGGER.error("Error %d on load url %s", request.code, + request.url) + return (None, None) + data += yield from request.read() + + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.error("Timeout for google speech.") + return (None, None) + + finally: + if request is not None: + yield from request.release() + + return ("mp3", data) + + @staticmethod + def _split_message_to_parts(message): + """Split message into single parts.""" + if len(message) <= MESSAGE_SIZE: + return [message] + + punc = "!()[]?.,;:" + punc_list = [re.escape(c) for c in punc] + pattern = '|'.join(punc_list) + parts = re.split(pattern, message) + + def split_by_space(fullstring): + """Split a string by space.""" + if len(fullstring) > MESSAGE_SIZE: + idx = fullstring.rfind(' ', 0, MESSAGE_SIZE) + return [fullstring[:idx]] + split_by_space(fullstring[idx:]) + else: + return [fullstring] + + msg_parts = [] + for part in parts: + msg_parts += split_by_space(part) + + return [msg for msg in msg_parts if len(msg) > 0] diff --git a/homeassistant/components/tts/services.yaml b/homeassistant/components/tts/services.yaml new file mode 100644 index 00000000000..aba1334da87 --- /dev/null +++ b/homeassistant/components/tts/services.yaml @@ -0,0 +1,14 @@ +say: + description: Say some things on a media player. + + fields: + entity_id: + description: Name(s) of media player entities + example: 'media_player.floor' + + message: + description: Text to speak on devices + example: 'My name is hanna' + +clear_cache: + description: Remove cache files and RAM cache. diff --git a/requirements_all.txt b/requirements_all.txt index 799b2b29b11..c85e3285e7e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -130,6 +130,9 @@ freesms==0.1.1 # homeassistant.components.conversation fuzzywuzzy==0.14.0 +# homeassistant.components.tts.google +gTTS-token==1.1.1 + # homeassistant.components.device_tracker.bluetooth_le_tracker # gattlib==0.20150805 diff --git a/tests/components/tts/__init__.py b/tests/components/tts/__init__.py new file mode 100644 index 00000000000..f5eb0731409 --- /dev/null +++ b/tests/components/tts/__init__.py @@ -0,0 +1 @@ +"""The tests for tts platforms.""" diff --git a/tests/components/tts/test_google.py b/tests/components/tts/test_google.py new file mode 100644 index 00000000000..623a96f1dfb --- /dev/null +++ b/tests/components/tts/test_google.py @@ -0,0 +1,199 @@ +"""The tests for the Google speech platform.""" +import asyncio +import os +import shutil +from unittest.mock import patch + +import homeassistant.components.tts as tts +from homeassistant.components.media_player import ( + SERVICE_PLAY_MEDIA, ATTR_MEDIA_CONTENT_ID, DOMAIN as DOMAIN_MP) +from homeassistant.bootstrap import setup_component + +from tests.common import ( + get_test_home_assistant, assert_setup_component, mock_service) + + +class TestTTSGooglePlatform(object): + """Test the Google speech component.""" + + def setup_method(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + + self.url = "http://translate.google.com/translate_tts" + self.url_param = { + 'tl': 'en', + 'q': 'I%20person%20is%20on%20front%20of%20your%20door.', + 'tk': 5, + 'client': 'tw-ob', + 'textlen': 34, + 'total': 1, + 'idx': 0, + 'ie': 'UTF-8', + } + + def teardown_method(self): + """Stop everything that was started.""" + default_tts = self.hass.config.path(tts.DEFAULT_CACHE_DIR) + if os.path.isdir(default_tts): + shutil.rmtree(default_tts) + + self.hass.stop() + + def test_setup_component(self): + """Test setup component.""" + config = { + tts.DOMAIN: { + 'platform': 'google', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + @patch('gtts_token.gtts_token.Token.calculate_token', autospec=True, + return_value=5) + def test_service_say(self, mock_calculate, aioclient_mock): + """Test service call say.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + aioclient_mock.get( + self.url, params=self.url_param, status=200, content=b'test') + + config = { + tts.DOMAIN: { + 'platform': 'google', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'google_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert len(aioclient_mock.mock_calls) == 1 + assert calls[0].data[ATTR_MEDIA_CONTENT_ID].find(".mp3") != -1 + + @patch('gtts_token.gtts_token.Token.calculate_token', autospec=True, + return_value=5) + def test_service_say_german(self, mock_calculate, aioclient_mock): + """Test service call say with german code.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + self.url_param['tl'] = 'de' + aioclient_mock.get( + self.url, params=self.url_param, status=200, content=b'test') + + config = { + tts.DOMAIN: { + 'platform': 'google', + 'language': 'de', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'google_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert len(aioclient_mock.mock_calls) == 1 + + @patch('gtts_token.gtts_token.Token.calculate_token', autospec=True, + return_value=5) + def test_service_say_error(self, mock_calculate, aioclient_mock): + """Test service call say with http response 400.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + aioclient_mock.get( + self.url, params=self.url_param, status=400, content=b'test') + + config = { + tts.DOMAIN: { + 'platform': 'google', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'google_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 0 + assert len(aioclient_mock.mock_calls) == 1 + + @patch('gtts_token.gtts_token.Token.calculate_token', autospec=True, + return_value=5) + def test_service_say_timeout(self, mock_calculate, aioclient_mock): + """Test service call say with http timeout.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + aioclient_mock.get( + self.url, params=self.url_param, exc=asyncio.TimeoutError()) + + config = { + tts.DOMAIN: { + 'platform': 'google', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'google_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 0 + assert len(aioclient_mock.mock_calls) == 1 + + @patch('gtts_token.gtts_token.Token.calculate_token', autospec=True, + return_value=5) + def test_service_say_long_size(self, mock_calculate, aioclient_mock): + """Test service call say with a lot of text.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + self.url_param['total'] = 9 + self.url_param['q'] = "I%20person%20is%20on%20front%20of%20your%20door" + self.url_param['textlen'] = 33 + for idx in range(0, 9): + self.url_param['idx'] = idx + aioclient_mock.get( + self.url, params=self.url_param, status=200, content=b'test') + + config = { + tts.DOMAIN: { + 'platform': 'google', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'google_say', { + tts.ATTR_MESSAGE: ("I person is on front of your door." + "I person is on front of your door." + "I person is on front of your door." + "I person is on front of your door." + "I person is on front of your door." + "I person is on front of your door." + "I person is on front of your door." + "I person is on front of your door." + "I person is on front of your door."), + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert len(aioclient_mock.mock_calls) == 9 + assert calls[0].data[ATTR_MEDIA_CONTENT_ID].find(".mp3") != -1 diff --git a/tests/components/tts/test_init.py b/tests/components/tts/test_init.py new file mode 100644 index 00000000000..fbdbddb8db5 --- /dev/null +++ b/tests/components/tts/test_init.py @@ -0,0 +1,320 @@ +"""The tests for the TTS component.""" +import os +import shutil +from unittest.mock import patch + +import requests + +import homeassistant.components.tts as tts +from homeassistant.components.tts.demo import DemoProvider +from homeassistant.components.media_player import ( + SERVICE_PLAY_MEDIA, MEDIA_TYPE_MUSIC, ATTR_MEDIA_CONTENT_ID, + ATTR_MEDIA_CONTENT_TYPE, DOMAIN as DOMAIN_MP) +from homeassistant.bootstrap import setup_component + +from tests.common import ( + get_test_home_assistant, assert_setup_component, mock_service) + + +class TestTTS(object): + """Test the Google speech component.""" + + def setup_method(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.demo_provider = DemoProvider() + self.default_tts_cache = self.hass.config.path(tts.DEFAULT_CACHE_DIR) + + def teardown_method(self): + """Stop everything that was started.""" + if os.path.isdir(self.default_tts_cache): + shutil.rmtree(self.default_tts_cache) + + self.hass.stop() + + def test_setup_component_demo(self): + """Setup the demo platform with defaults.""" + config = { + tts.DOMAIN: { + 'platform': 'demo', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + assert self.hass.services.has_service(tts.DOMAIN, 'demo_say') + assert self.hass.services.has_service(tts.DOMAIN, 'clear_cache') + + @patch('os.mkdir', side_effect=OSError(2, "No access")) + def test_setup_component_demo_no_access_cache_folder(self, mock_mkdir): + """Setup the demo platform with defaults.""" + config = { + tts.DOMAIN: { + 'platform': 'demo', + } + } + + assert not setup_component(self.hass, tts.DOMAIN, config) + + assert not self.hass.services.has_service(tts.DOMAIN, 'demo_say') + assert not self.hass.services.has_service(tts.DOMAIN, 'clear_cache') + + def test_setup_component_and_test_service(self): + """Setup the demo platform and call service.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + config = { + tts.DOMAIN: { + 'platform': 'demo', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'demo_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MEDIA_TYPE_MUSIC + assert calls[0].data[ATTR_MEDIA_CONTENT_ID].find( + "/api/tts_proxy/265944c108cbb00b2a621be5930513e03a0bb2cd" + "_demo.mp3") \ + != -1 + assert os.path.isfile(os.path.join( + self.default_tts_cache, + "265944c108cbb00b2a621be5930513e03a0bb2cd_demo.mp3")) + + def test_setup_component_and_test_service_clear_cache(self): + """Setup the demo platform and call service clear cache.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + config = { + tts.DOMAIN: { + 'platform': 'demo', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'demo_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert os.path.isfile(os.path.join( + self.default_tts_cache, + "265944c108cbb00b2a621be5930513e03a0bb2cd_demo.mp3")) + + self.hass.services.call(tts.DOMAIN, tts.SERVICE_CLEAR_CACHE, {}) + self.hass.block_till_done() + + assert not os.path.isfile(os.path.join( + self.default_tts_cache, + "265944c108cbb00b2a621be5930513e03a0bb2cd_demo.mp3")) + + def test_setup_component_and_test_service_with_receive_voice(self): + """Setup the demo platform and call service and receive voice.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + config = { + tts.DOMAIN: { + 'platform': 'demo', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.start() + + self.hass.services.call(tts.DOMAIN, 'demo_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 1 + req = requests.get(calls[0].data[ATTR_MEDIA_CONTENT_ID]) + _, demo_data = self.demo_provider.get_tts_audio("bla") + assert req.status_code == 200 + assert req.content == demo_data + + def test_setup_component_and_web_view_wrong_file(self): + """Setup the demo platform and receive wrong file from web.""" + config = { + tts.DOMAIN: { + 'platform': 'demo', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.start() + + url = ("{}/api/tts_proxy/265944c108cbb00b2a621be5930513e03a0bb2cd" + "_demo.mp3").format(self.hass.config.api.base_url) + + req = requests.get(url) + assert req.status_code == 404 + + def test_setup_component_and_web_view_wrong_filename(self): + """Setup the demo platform and receive wrong filename from web.""" + config = { + tts.DOMAIN: { + 'platform': 'demo', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.start() + + url = ("{}/api/tts_proxy/265944dsk32c1b2a621be5930510bb2cd" + "_demo.mp3").format(self.hass.config.api.base_url) + + req = requests.get(url) + assert req.status_code == 404 + + def test_setup_component_test_without_cache(self): + """Setup demo platform without cache.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + config = { + tts.DOMAIN: { + 'platform': 'demo', + 'cache': False, + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'demo_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert not os.path.isfile(os.path.join( + self.default_tts_cache, + "265944c108cbb00b2a621be5930513e03a0bb2cd_demo.mp3")) + + def test_setup_component_test_with_cache_call_service_without_cache(self): + """Setup demo platform with cache and call service without cache.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + config = { + tts.DOMAIN: { + 'platform': 'demo', + 'cache': True, + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'demo_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + tts.ATTR_CACHE: False, + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert not os.path.isfile(os.path.join( + self.default_tts_cache, + "265944c108cbb00b2a621be5930513e03a0bb2cd_demo.mp3")) + + def test_setup_component_test_with_cache_dir(self): + """Setup demo platform with cache and call service without cache.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + _, demo_data = self.demo_provider.get_tts_audio("bla") + cache_file = os.path.join( + self.default_tts_cache, + "265944c108cbb00b2a621be5930513e03a0bb2cd_demo.mp3") + + os.mkdir(self.default_tts_cache) + with open(cache_file, "wb") as voice_file: + voice_file.write(demo_data) + + config = { + tts.DOMAIN: { + 'platform': 'demo', + 'cache': True, + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + with patch('homeassistant.components.tts.demo.DemoProvider.' + 'get_tts_audio', return_value=None): + self.hass.services.call(tts.DOMAIN, 'demo_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert calls[0].data[ATTR_MEDIA_CONTENT_ID].find( + "/api/tts_proxy/265944c108cbb00b2a621be5930513e03a0bb2cd" + "_demo.mp3") \ + != -1 + + @patch('homeassistant.components.tts.demo.DemoProvider.get_tts_audio', + return_value=None) + def test_setup_component_test_with_error_on_get_tts(self, tts_mock): + """Setup demo platform with wrong get_tts_audio.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + config = { + tts.DOMAIN: { + 'platform': 'demo' + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'demo_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 0 + + def test_setup_component_load_cache_retrieve_without_mem_cache(self): + """Setup component and load cache and get without mem cache.""" + _, demo_data = self.demo_provider.get_tts_audio("bla") + cache_file = os.path.join( + self.default_tts_cache, + "265944c108cbb00b2a621be5930513e03a0bb2cd_demo.mp3") + + os.mkdir(self.default_tts_cache) + with open(cache_file, "wb") as voice_file: + voice_file.write(demo_data) + + config = { + tts.DOMAIN: { + 'platform': 'demo', + 'cache': True, + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.start() + + url = ("{}/api/tts_proxy/265944c108cbb00b2a621be5930513e03a0bb2cd" + "_demo.mp3").format(self.hass.config.api.base_url) + + req = requests.get(url) + assert req.status_code == 200 + assert req.content == demo_data diff --git a/tests/test_util/aiohttp.py b/tests/test_util/aiohttp.py index d6f0c80b435..4abf43a6e42 100644 --- a/tests/test_util/aiohttp.py +++ b/tests/test_util/aiohttp.py @@ -23,6 +23,7 @@ class AiohttpClientMocker: content=None, json=None, params=None, + headers=None, exc=None): """Mock a request.""" if json: @@ -65,8 +66,8 @@ class AiohttpClientMocker: return len(self.mock_calls) @asyncio.coroutine - def match_request(self, method, url, *, auth=None, params=None): \ - # pylint: disable=unused-variable + def match_request(self, method, url, *, auth=None, params=None, + headers=None): # pylint: disable=unused-variable """Match a request against pre-registered requests.""" for response in self._mocks: if response.match_request(method, url, params): @@ -76,8 +77,8 @@ class AiohttpClientMocker: raise self.exc return response - assert False, "No mock registered for {} {}".format(method.upper(), - url) + assert False, "No mock registered for {} {} {}".format(method.upper(), + url, params) class AiohttpClientMockResponse: From 72bd9fb5c7cc4c65fa74fe3bbfa120b7e7feefed Mon Sep 17 00:00:00 2001 From: Audun Ytterdal Date: Tue, 13 Dec 2016 17:53:42 +0100 Subject: [PATCH 095/141] Remove libtelldus-core-dev from Dockerfile (#4878) Remove unnecessary libtelldus-core-dev from Dockerfile . Ref https://github.com/home-assistant/home-assistant/pull/4680#issuecomment-266006310 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 02e3db616ae..634edb8af59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ RUN echo "deb http://download.telldus.com/debian/ stable main" >> /etc/apt/sourc wget -qO - http://download.telldus.se/debian/telldus-public.key | apt-key add - && \ apt-get update && \ apt-get install -y --no-install-recommends nmap net-tools cython3 libudev-dev sudo libglib2.0-dev bluetooth libbluetooth-dev \ - libtelldus-core2 libtelldus-core-dev && \ + libtelldus-core2 && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* COPY script/build_python_openzwave script/build_python_openzwave From e4b6395250022a9badb5d776d187499c23606a68 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 13 Dec 2016 17:55:13 +0100 Subject: [PATCH 096/141] Migrate REST switch to async (#4517) * Migrate REST switch to async * Update rest.py * Address comments from paulus --- homeassistant/components/switch/rest.py | 108 ++++++++--- tests/components/switch/test_rest.py | 228 +++++++++++++----------- tests/test_util/aiohttp.py | 5 +- 3 files changed, 204 insertions(+), 137 deletions(-) diff --git a/homeassistant/components/switch/rest.py b/homeassistant/components/switch/rest.py index 36674c16d16..cfa11897de9 100644 --- a/homeassistant/components/switch/rest.py +++ b/homeassistant/components/switch/rest.py @@ -4,23 +4,27 @@ Support for RESTful switches. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/switch.rest/ """ +import asyncio import logging -import requests +import aiohttp +import async_timeout import voluptuous as vol from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) from homeassistant.const import (CONF_NAME, CONF_RESOURCE, CONF_TIMEOUT) +from homeassistant.helpers.aiohttp_client import async_get_clientsession import homeassistant.helpers.config_validation as cv from homeassistant.helpers.template import Template CONF_BODY_OFF = 'body_off' CONF_BODY_ON = 'body_on' +CONF_IS_ON_TEMPLATE = 'is_on_template' + DEFAULT_BODY_OFF = Template('OFF') DEFAULT_BODY_ON = Template('ON') DEFAULT_NAME = 'REST Switch' DEFAULT_TIMEOUT = 10 -CONF_IS_ON_TEMPLATE = 'is_on_template' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_RESOURCE): cv.url, @@ -35,13 +39,15 @@ _LOGGER = logging.getLogger(__name__) # pylint: disable=unused-argument, -def setup_platform(hass, config, add_devices, discovery_info=None): +@asyncio.coroutine +def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the RESTful switch.""" name = config.get(CONF_NAME) resource = config.get(CONF_RESOURCE) body_on = config.get(CONF_BODY_ON) body_off = config.get(CONF_BODY_OFF) is_on_template = config.get(CONF_IS_ON_TEMPLATE) + websession = async_get_clientsession(hass) if is_on_template is not None: is_on_template.hass = hass @@ -51,19 +57,24 @@ def setup_platform(hass, config, add_devices, discovery_info=None): body_off.hass = hass timeout = config.get(CONF_TIMEOUT) + req = None try: - requests.get(resource, timeout=10) - except requests.exceptions.MissingSchema: + with async_timeout.timeout(timeout, loop=hass.loop): + req = yield from websession.get(resource) + except (TypeError, ValueError): _LOGGER.error("Missing resource or schema in configuration. " "Add http:// or https:// to your URL") return False - except requests.exceptions.ConnectionError: + except (asyncio.TimeoutError, aiohttp.errors.ClientError): _LOGGER.error("No route to resource/endpoint: %s", resource) return False + finally: + if req is not None: + yield from req.release() - add_devices( - [RestSwitch( - hass, name, resource, body_on, body_off, is_on_template, timeout)]) + yield from async_add_devices( + [RestSwitch(hass, name, resource, body_on, body_off, + is_on_template, timeout)]) class RestSwitch(SwitchDevice): @@ -73,7 +84,7 @@ class RestSwitch(SwitchDevice): is_on_template, timeout): """Initialize the REST switch.""" self._state = None - self._hass = hass + self.hass = hass self._name = name self._resource = resource self._body_on = body_on @@ -91,46 +102,85 @@ class RestSwitch(SwitchDevice): """Return true if device is on.""" return self._state - def turn_on(self, **kwargs): + @asyncio.coroutine + def async_turn_on(self, **kwargs): """Turn the device on.""" - body_on_t = self._body_on.render() - request = requests.post( - self._resource, data=body_on_t, timeout=self._timeout) - if request.status_code == 200: + body_on_t = self._body_on.async_render() + websession = async_get_clientsession(self.hass) + + request = None + try: + with async_timeout.timeout(self._timeout, loop=self.hass.loop): + request = yield from websession.post( + self._resource, data=bytes(body_on_t, 'utf-8')) + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.error("Error while turn on %s", self._resource) + return + finally: + if request is not None: + yield from request.release() + + if request.status == 200: self._state = True else: _LOGGER.error("Can't turn on %s. Is resource/endpoint offline?", self._resource) - def turn_off(self, **kwargs): + @asyncio.coroutine + def async_turn_off(self, **kwargs): """Turn the device off.""" - body_off_t = self._body_off.render() - request = requests.post( - self._resource, data=body_off_t, timeout=self._timeout) - if request.status_code == 200: + body_off_t = self._body_off.async_render() + websession = async_get_clientsession(self.hass) + + request = None + try: + with async_timeout.timeout(self._timeout, loop=self.hass.loop): + request = yield from websession.post( + self._resource, data=bytes(body_off_t, 'utf-8')) + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.error("Error while turn off %s", self._resource) + return + finally: + if request is not None: + yield from request.release() + + if request.status == 200: self._state = False else: _LOGGER.error("Can't turn off %s. Is resource/endpoint offline?", self._resource) - def update(self): + @asyncio.coroutine + def async_update(self): """Get the latest data from REST API and update the state.""" - request = requests.get(self._resource, timeout=self._timeout) + websession = async_get_clientsession(self.hass) + + request = None + try: + with async_timeout.timeout(self._timeout, loop=self.hass.loop): + request = yield from websession.get(self._resource) + text = yield from request.text() + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.exception("Error while fetch data.") + return + finally: + if request is not None: + yield from request.release() if self._is_on_template is not None: - response = self._is_on_template.render_with_possible_json_value( - request.text, 'None') - response = response.lower() - if response == 'true': + text = self._is_on_template.async_render_with_possible_json_value( + text, 'None') + text = text.lower() + if text == 'true': self._state = True - elif response == 'false': + elif text == 'false': self._state = False else: self._state = None else: - if request.text == self._body_on.template: + if text == self._body_on.template: self._state = True - elif request.text == self._body_off.template: + elif text == self._body_off.template: self._state = False else: self._state = None diff --git a/tests/components/switch/test_rest.py b/tests/components/switch/test_rest.py index dc6c58db928..38ddad5e9a2 100644 --- a/tests/components/switch/test_rest.py +++ b/tests/components/switch/test_rest.py @@ -1,76 +1,83 @@ """The tests for the REST switch platform.""" -import unittest -from unittest.mock import patch +import asyncio -import pytest -import requests -from requests.exceptions import Timeout -import requests_mock +import aiohttp import homeassistant.components.switch.rest as rest from homeassistant.bootstrap import setup_component +from homeassistant.util.async import run_coroutine_threadsafe +from homeassistant.helpers.template import Template from tests.common import get_test_home_assistant, assert_setup_component -class TestRestSwitchSetup(unittest.TestCase): +class TestRestSwitchSetup: """Tests for setting up the REST switch platform.""" - def setUp(self): + def setup_method(self): """Setup things to be run when tests are started.""" self.hass = get_test_home_assistant() - def tearDown(self): + def teardown_method(self): """Stop everything that was started.""" self.hass.stop() def test_setup_missing_config(self): """Test setup with configuration missing required entries.""" - self.assertFalse(rest.setup_platform(self.hass, { - 'platform': 'rest' - }, None)) + assert not run_coroutine_threadsafe( + rest.async_setup_platform(self.hass, { + 'platform': 'rest' + }, None), + self.hass.loop + ).result() def test_setup_missing_schema(self): """Test setup with resource missing schema.""" - self.assertFalse(rest.setup_platform(self.hass, { - 'platform': 'rest', - 'resource': 'localhost' - }, None)) + assert not run_coroutine_threadsafe( + rest.async_setup_platform(self.hass, { + 'platform': 'rest', + 'resource': 'localhost' + }, None), + self.hass.loop + ).result() - @patch('requests.get', side_effect=requests.exceptions.ConnectionError()) - def test_setup_failed_connect(self, mock_req): + def test_setup_failed_connect(self, aioclient_mock): """Test setup when connection error occurs.""" - self.assertFalse(rest.setup_platform(self.hass, { - 'platform': 'rest', - 'resource': 'http://localhost', - }, None)) - - @patch('requests.get', side_effect=Timeout()) - def test_setup_timeout(self, mock_req): - """Test setup when connection timeout occurs.""" - with self.assertRaises(Timeout): - rest.setup_platform(self.hass, { + aioclient_mock.get('http://localhost', exc=aiohttp.errors.ClientError) + assert not run_coroutine_threadsafe( + rest.async_setup_platform(self.hass, { 'platform': 'rest', 'resource': 'http://localhost', - }, None) + }, None), + self.hass.loop + ).result() - @requests_mock.Mocker() - def test_setup_minimum(self, mock_req): - """Test setup with minimum configuration.""" - mock_req.get('http://localhost', status_code=200) - self.assertTrue(setup_component(self.hass, 'switch', { - 'switch': { + def test_setup_timeout(self, aioclient_mock): + """Test setup when connection timeout occurs.""" + aioclient_mock.get('http://localhost', exc=asyncio.TimeoutError()) + assert not run_coroutine_threadsafe( + rest.async_setup_platform(self.hass, { 'platform': 'rest', - 'resource': 'http://localhost' - } - })) - self.assertEqual(1, mock_req.call_count) - assert_setup_component(1, 'switch') + 'resource': 'http://localhost', + }, None), + self.hass.loop + ).result() - @requests_mock.Mocker() - def test_setup(self, mock_req): + def test_setup_minimum(self, aioclient_mock): + """Test setup with minimum configuration.""" + aioclient_mock.get('http://localhost', status=200) + with assert_setup_component(1, 'switch'): + assert setup_component(self.hass, 'switch', { + 'switch': { + 'platform': 'rest', + 'resource': 'http://localhost' + } + }) + assert aioclient_mock.call_count == 1 + + def test_setup(self, aioclient_mock): """Test setup with valid configuration.""" - mock_req.get('localhost', status_code=200) - self.assertTrue(setup_component(self.hass, 'switch', { + aioclient_mock.get('http://localhost', status=200) + assert setup_component(self.hass, 'switch', { 'switch': { 'platform': 'rest', 'name': 'foo', @@ -78,111 +85,120 @@ class TestRestSwitchSetup(unittest.TestCase): 'body_on': 'custom on text', 'body_off': 'custom off text', } - })) - self.assertEqual(1, mock_req.call_count) + }) + assert aioclient_mock.call_count == 1 assert_setup_component(1, 'switch') -@pytest.mark.skip -class TestRestSwitch(unittest.TestCase): +class TestRestSwitch: """Tests for REST switch platform.""" - def setUp(self): + def setup_method(self): """Setup things to be run when tests are started.""" self.hass = get_test_home_assistant() self.name = 'foo' self.resource = 'http://localhost/' - self.body_on = 'on' - self.body_off = 'off' + self.body_on = Template('on', self.hass) + self.body_off = Template('off', self.hass) self.switch = rest.RestSwitch(self.hass, self.name, self.resource, - self.body_on, self.body_off) + self.body_on, self.body_off, None, 10) - def tearDown(self): + def teardown_method(self): """Stop everything that was started.""" self.hass.stop() def test_name(self): """Test the name.""" - self.assertEqual(self.name, self.switch.name) + assert self.name == self.switch.name def test_is_on_before_update(self): """Test is_on in initial state.""" - self.assertEqual(None, self.switch.is_on) + assert self.switch.is_on is None - @requests_mock.Mocker() - def test_turn_on_success(self, mock_req): + def test_turn_on_success(self, aioclient_mock): """Test turn_on.""" - mock_req.post(self.resource, status_code=200) - self.switch.turn_on() + aioclient_mock.post(self.resource, status=200) + run_coroutine_threadsafe( + self.switch.async_turn_on(), self.hass.loop).result() - self.assertEqual(self.body_on, mock_req.last_request.text) - self.assertEqual(True, self.switch.is_on) + assert self.body_on.template == \ + aioclient_mock.mock_calls[-1][2].decode() + assert self.switch.is_on - @requests_mock.Mocker() - def test_turn_on_status_not_ok(self, mock_req): + def test_turn_on_status_not_ok(self, aioclient_mock): """Test turn_on when error status returned.""" - mock_req.post(self.resource, status_code=500) - self.switch.turn_on() + aioclient_mock.post(self.resource, status=500) + run_coroutine_threadsafe( + self.switch.async_turn_on(), self.hass.loop).result() - self.assertEqual(self.body_on, mock_req.last_request.text) - self.assertEqual(None, self.switch.is_on) + assert self.body_on.template == \ + aioclient_mock.mock_calls[-1][2].decode() + assert self.switch.is_on is None - @patch('requests.post', side_effect=Timeout()) - def test_turn_on_timeout(self, mock_req): + def test_turn_on_timeout(self, aioclient_mock): """Test turn_on when timeout occurs.""" - with self.assertRaises(Timeout): - self.switch.turn_on() + aioclient_mock.post(self.resource, status=500) + run_coroutine_threadsafe( + self.switch.async_turn_on(), self.hass.loop).result() - @requests_mock.Mocker() - def test_turn_off_success(self, mock_req): + assert self.switch.is_on is None + + def test_turn_off_success(self, aioclient_mock): """Test turn_off.""" - mock_req.post(self.resource, status_code=200) - self.switch.turn_off() + aioclient_mock.post(self.resource, status=200) + run_coroutine_threadsafe( + self.switch.async_turn_off(), self.hass.loop).result() - self.assertEqual(self.body_off, mock_req.last_request.text) - self.assertEqual(False, self.switch.is_on) + assert self.body_off.template == \ + aioclient_mock.mock_calls[-1][2].decode() + assert not self.switch.is_on - @requests_mock.Mocker() - def test_turn_off_status_not_ok(self, mock_req): + def test_turn_off_status_not_ok(self, aioclient_mock): """Test turn_off when error status returned.""" - mock_req.post(self.resource, status_code=500) - self.switch.turn_off() + aioclient_mock.post(self.resource, status=500) + run_coroutine_threadsafe( + self.switch.async_turn_off(), self.hass.loop).result() - self.assertEqual(self.body_off, mock_req.last_request.text) - self.assertEqual(None, self.switch.is_on) + assert self.body_off.template == \ + aioclient_mock.mock_calls[-1][2].decode() + assert self.switch.is_on is None - @patch('requests.post', side_effect=Timeout()) - def test_turn_off_timeout(self, mock_req): + def test_turn_off_timeout(self, aioclient_mock): """Test turn_off when timeout occurs.""" - with self.assertRaises(Timeout): - self.switch.turn_on() + aioclient_mock.post(self.resource, exc=asyncio.TimeoutError()) + run_coroutine_threadsafe( + self.switch.async_turn_on(), self.hass.loop).result() - @requests_mock.Mocker() - def test_update_when_on(self, mock_req): + assert self.switch.is_on is None + + def test_update_when_on(self, aioclient_mock): """Test update when switch is on.""" - mock_req.get(self.resource, text=self.body_on) - self.switch.update() + aioclient_mock.get(self.resource, text=self.body_on.template) + run_coroutine_threadsafe( + self.switch.async_update(), self.hass.loop).result() - self.assertEqual(True, self.switch.is_on) + assert self.switch.is_on - @requests_mock.Mocker() - def test_update_when_off(self, mock_req): + def test_update_when_off(self, aioclient_mock): """Test update when switch is off.""" - mock_req.get(self.resource, text=self.body_off) - self.switch.update() + aioclient_mock.get(self.resource, text=self.body_off.template) + run_coroutine_threadsafe( + self.switch.async_update(), self.hass.loop).result() - self.assertEqual(False, self.switch.is_on) + assert not self.switch.is_on - @requests_mock.Mocker() - def test_update_when_unknown(self, mock_req): + def test_update_when_unknown(self, aioclient_mock): """Test update when unknown status returned.""" - mock_req.get(self.resource, text='unknown status') - self.switch.update() + aioclient_mock.get(self.resource, text='unknown status') + run_coroutine_threadsafe( + self.switch.async_update(), self.hass.loop).result() - self.assertEqual(None, self.switch.is_on) + assert self.switch.is_on is None - @patch('requests.get', side_effect=Timeout()) - def test_update_timeout(self, mock_req): + def test_update_timeout(self, aioclient_mock): """Test update when timeout occurs.""" - with self.assertRaises(Timeout): - self.switch.update() + aioclient_mock.get(self.resource, exc=asyncio.TimeoutError()) + run_coroutine_threadsafe( + self.switch.async_update(), self.hass.loop).result() + + assert self.switch.is_on is None diff --git a/tests/test_util/aiohttp.py b/tests/test_util/aiohttp.py index 4abf43a6e42..c0ed579f197 100644 --- a/tests/test_util/aiohttp.py +++ b/tests/test_util/aiohttp.py @@ -20,6 +20,7 @@ class AiohttpClientMocker: auth=None, status=200, text=None, + data=None, content=None, json=None, params=None, @@ -66,12 +67,12 @@ class AiohttpClientMocker: return len(self.mock_calls) @asyncio.coroutine - def match_request(self, method, url, *, auth=None, params=None, + def match_request(self, method, url, *, data=None, auth=None, params=None, headers=None): # pylint: disable=unused-variable """Match a request against pre-registered requests.""" for response in self._mocks: if response.match_request(method, url, params): - self.mock_calls.append((method, url)) + self.mock_calls.append((method, url, data)) if self.exc: raise self.exc From 6da3e23436bdf6e7690696fcd80df9634b6f2f80 Mon Sep 17 00:00:00 2001 From: Erik Eriksson Date: Tue, 13 Dec 2016 17:57:33 +0100 Subject: [PATCH 097/141] Update __init__.py (#4877) Cleaner exit by not throwing exception if server was not set during initialization of component (ref https://github.com/home-assistant/home-assistant/pull/4866) --- homeassistant/components/http/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/http/__init__.py b/homeassistant/components/http/__init__.py index bfc5d662105..446b1f5f28b 100644 --- a/homeassistant/components/http/__init__.py +++ b/homeassistant/components/http/__init__.py @@ -323,10 +323,12 @@ class HomeAssistantWSGI(object): @asyncio.coroutine def stop(self): """Stop the wsgi server.""" - self.server.close() - yield from self.server.wait_closed() + if self.server: + self.server.close() + yield from self.server.wait_closed() yield from self.app.shutdown() - yield from self._handler.finish_connections(60.0) + if self._handler: + yield from self._handler.finish_connections(60.0) yield from self.app.cleanup() From dc551b825fb94fa6a708aed3524642073291065b Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 14 Dec 2016 05:04:40 +0100 Subject: [PATCH 098/141] =?UTF-8?q?Added=20a=20volume=20set=20option=20and?= =?UTF-8?q?=20autodiscovery=20functions=20to=20Denon=20AVR=20rece=E2=80=A6?= =?UTF-8?q?=20(#4845)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added Volume Set option and autodiscovery functions to Denon AVR receivers * Corrected issues in SSDP discovery and in case no host could be discovered * Corrected discovery handling / added denonavr to discovery platform * No needless discoveries anymore / add_devices() with list instead of loop --- homeassistant/components/discovery.py | 3 +- .../components/media_player/denonavr.py | 78 ++++++++++++++++--- requirements_all.txt | 4 +- 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py index 3c4dff6eac5..74dc5d69220 100644 --- a/homeassistant/components/discovery.py +++ b/homeassistant/components/discovery.py @@ -14,7 +14,7 @@ import voluptuous as vol from homeassistant.const import EVENT_HOMEASSISTANT_START from homeassistant.helpers.discovery import load_platform, discover -REQUIREMENTS = ['netdisco==0.8.0'] +REQUIREMENTS = ['netdisco==0.8.1'] DOMAIN = 'discovery' @@ -36,6 +36,7 @@ SERVICE_HANDLERS = { 'yamaha': ('media_player', 'yamaha'), 'logitech_mediaserver': ('media_player', 'squeezebox'), 'directv': ('media_player', 'directv'), + 'denonavr': ('media_player', 'denonavr'), } CONFIG_SCHEMA = vol.Schema({ diff --git a/homeassistant/components/media_player/denonavr.py b/homeassistant/components/media_player/denonavr.py index 6db223bc6ec..5784fd6c829 100644 --- a/homeassistant/components/media_player/denonavr.py +++ b/homeassistant/components/media_player/denonavr.py @@ -13,26 +13,27 @@ from homeassistant.components.media_player import ( SUPPORT_TURN_OFF, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE, SUPPORT_PLAY_MEDIA, MEDIA_TYPE_CHANNEL, MediaPlayerDevice, PLATFORM_SCHEMA, SUPPORT_TURN_ON, - MEDIA_TYPE_MUSIC) + MEDIA_TYPE_MUSIC, SUPPORT_VOLUME_SET) from homeassistant.const import ( CONF_HOST, STATE_OFF, STATE_PLAYING, STATE_PAUSED, CONF_NAME, STATE_ON) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['denonavr==0.1.6'] +REQUIREMENTS = ['denonavr==0.2.2'] _LOGGER = logging.getLogger(__name__) DEFAULT_NAME = None +KEY_DENON_CACHE = 'denonavr_hosts' SUPPORT_DENON = SUPPORT_VOLUME_STEP | SUPPORT_VOLUME_MUTE | \ SUPPORT_TURN_ON | SUPPORT_TURN_OFF | \ SUPPORT_SELECT_SOURCE | SUPPORT_PLAY_MEDIA | \ SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | \ - SUPPORT_NEXT_TRACK + SUPPORT_NEXT_TRACK | SUPPORT_VOLUME_SET PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_HOST): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, }) @@ -41,11 +42,53 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Denon platform.""" import denonavr - receiver = denonavr.DenonAVR(config.get(CONF_HOST), config.get(CONF_NAME)) + # Initialize list with receivers to be started + receivers = [] - add_devices([DenonDevice(receiver)]) - _LOGGER.info("Denon receiver at host %s initialized", - config.get(CONF_HOST)) + cache = hass.data.get(KEY_DENON_CACHE) + if cache is None: + cache = hass.data[KEY_DENON_CACHE] = set() + + # Start assignment of host and name + # 1. option: manual setting + if config.get(CONF_HOST) is not None: + host = config.get(CONF_HOST) + name = config.get(CONF_NAME) + # Check if host not in cache, append it and save for later starting + if host not in cache: + cache.add(host) + receivers.append( + DenonDevice(denonavr.DenonAVR(host, name))) + _LOGGER.info("Denon receiver at host %s initialized", host) + # 2. option: discovery using netdisco + if discovery_info is not None: + host = discovery_info[0] + name = discovery_info[1] + # Check if host not in cache, append it and save for later starting + if host not in cache: + cache.add(host) + receivers.append( + DenonDevice(denonavr.DenonAVR(host, name))) + _LOGGER.info("Denon receiver at host %s initialized", host) + # 3. option: discovery using denonavr library + if config.get(CONF_HOST) is None and discovery_info is None: + d_receivers = denonavr.discover() + # More than one receiver could be discovered by that method + if d_receivers is not None: + for d_receiver in d_receivers: + host = d_receiver["host"] + name = d_receiver["friendlyName"] + # Check if host not in cache, append it and save for later + # starting + if host not in cache: + cache.add(host) + receivers.append( + DenonDevice(denonavr.DenonAVR(host, name))) + _LOGGER.info("Denon receiver at host %s initialized", host) + + # Add all freshly discovered receivers + if receivers: + add_devices(receivers) class DenonDevice(MediaPlayerDevice): @@ -107,7 +150,8 @@ class DenonDevice(MediaPlayerDevice): @property def volume_level(self): """Volume level of the media player (0..1).""" - # Volume is send in a format like -50.0. Minimum is around -80.0 + # Volume is sent in a format like -50.0. Minimum is -80.0, + # maximum is 18.0 return (float(self._volume) + 80) / 100 @property @@ -240,6 +284,22 @@ class DenonDevice(MediaPlayerDevice): """Volume down media player.""" return self._receiver.volume_down() + def set_volume_level(self, volume): + """Set volume level, range 0..1.""" + # Volume has to be sent in a format like -50.0. Minimum is -80.0, + # maximum is 18.0 + volume_denon = float((volume * 100) - 80) + if volume_denon > 18: + volume_denon = float(18) + try: + if self._receiver.set_volume(volume_denon): + self._volume = volume_denon + return True + else: + return False + except ValueError: + return False + def mute_volume(self, mute): """Send mute command.""" return self._receiver.mute(mute) diff --git a/requirements_all.txt b/requirements_all.txt index c85e3285e7e..924f534145d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -76,7 +76,7 @@ colorlog>2.1,<3 concord232==0.14 # homeassistant.components.media_player.denonavr -denonavr==0.1.6 +denonavr==0.2.2 # homeassistant.components.media_player.directv directpy==0.1 @@ -302,7 +302,7 @@ mficlient==0.3.0 miflora==0.1.13 # homeassistant.components.discovery -netdisco==0.8.0 +netdisco==0.8.1 # homeassistant.components.sensor.neurio_energy neurio==0.2.10 From 570cfc60c54ea073ada7d157e4f6b19950eb6b34 Mon Sep 17 00:00:00 2001 From: Erik Eriksson Date: Wed, 14 Dec 2016 07:58:43 +0100 Subject: [PATCH 099/141] bugfix: is_on is a property (#4889) --- homeassistant/components/switch/tellduslive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/switch/tellduslive.py b/homeassistant/components/switch/tellduslive.py index b1450de6c5e..5f3901d79b8 100644 --- a/homeassistant/components/switch/tellduslive.py +++ b/homeassistant/components/switch/tellduslive.py @@ -28,7 +28,7 @@ class TelldusLiveSwitch(TelldusLiveEntity, ToggleEntity): @property def is_on(self): """Return true if switch is on.""" - return self.device.is_on() + return self.device.is_on def turn_on(self, **kwargs): """Turn the switch on.""" From 7ca025f653a3bfe008bf1d3ef7fdb17b3a429fcf Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Wed, 14 Dec 2016 02:01:14 -0500 Subject: [PATCH 100/141] Fixes issues #4844 to avoid traceback when self.rest.data is None (#4886) 6-12-09 18:12:30 homeassistant.core: Error doing job: Task exception was never retrieved Traceback (most recent call last): File "/usr/lib/python3.4/asyncio/tasks.py", line 237, in _step result = next(coro) File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/helpers/entity_component.py", line 386, in _update_entity_states yield from update_coro File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/helpers/entity.py", line 240, in async_update_ha_state self._attr_setter('entity_picture', str, ATTR_ENTITY_PICTURE, attr) File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/helpers/entity.py", line 307, in _attr_setter value = getattr(self, name) File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/components/sensor/wunderground.py", line 176, in entity_picture url = self.rest.data['icon_url'] TypeError: 'NoneType' object is not subscriptable --- homeassistant/components/sensor/wunderground.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/wunderground.py b/homeassistant/components/sensor/wunderground.py index 2f6558cd9da..67e19f225d5 100644 --- a/homeassistant/components/sensor/wunderground.py +++ b/homeassistant/components/sensor/wunderground.py @@ -196,7 +196,7 @@ class WUndergroundSensor(Entity): @property def entity_picture(self): """Return the entity picture.""" - if self._condition == 'weather': + if self.rest.data and self._condition == 'weather': url = self.rest.data['icon_url'] return re.sub(r'^http://', 'https://', url, flags=re.IGNORECASE) From da6bdf275e79b82c4eeaac3662db9a05deb3d465 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 13 Dec 2016 23:29:54 -0800 Subject: [PATCH 101/141] Update frontend --- homeassistant/components/frontend/version.py | 6 +++--- .../components/frontend/www_static/core.js | 8 ++++---- .../components/frontend/www_static/core.js.gz | Bin 33524 -> 32904 bytes .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 130643 -> 130940 bytes .../www_static/home-assistant-polymer | 2 +- .../panels/ha-panel-dev-service.html | 2 +- .../panels/ha-panel-dev-service.html.gz | Bin 17764 -> 17796 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2323 -> 2326 bytes 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index e6211c145e2..f316a07dab9 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -1,13 +1,13 @@ """DO NOT MODIFY. Auto-generated by script/fingerprint_frontend.""" FINGERPRINTS = { - "core.js": "5dfb2d3e567fad37af0321d4b29265ed", - "frontend.html": "ac15b11435132aab3da592f9e7b05400", + "core.js": "ad1ebcd0614c98a390d982087a7ca75c", + "frontend.html": "920bb20410f9a1b8458600b15a1d40ae", "mdi.html": "46a76f877ac9848899b8ed382427c16f", "micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a", "panels/ha-panel-dev-event.html": "c2d5ec676be98d4474d19f94d0262c1e", "panels/ha-panel-dev-info.html": "a9c07bf281fe9791fb15827ec1286825", - "panels/ha-panel-dev-service.html": "20420e2387fd93db53c8d778097e3d59", + "panels/ha-panel-dev-service.html": "ac74f7ce66fd7136d25c914ea12f4351", "panels/ha-panel-dev-state.html": "65e5f791cc467561719bf591f1386054", "panels/ha-panel-dev-template.html": "7d744ab7f7c08b6d6ad42069989de400", "panels/ha-panel-history.html": "efe1bcdd7733b09e55f4f965d171c295", diff --git a/homeassistant/components/frontend/www_static/core.js b/homeassistant/components/frontend/www_static/core.js index a70b70d2fd8..6cab0b713f3 100644 --- a/homeassistant/components/frontend/www_static/core.js +++ b/homeassistant/components/frontend/www_static/core.js @@ -1,4 +1,4 @@ -!(function(){"use strict";function t(t){return t&&t.__esModule?t.default:t}function e(t,e){return e={exports:{}},t(e,e.exports),e.exports}function n(t,e){var n=e.authToken,r=e.host;return xe({authToken:n,host:r,isValidating:!0,isInvalid:!1,errorMessage:""})}function r(){return Ve.getInitialState()}function i(t,e){var n=e.errorMessage;return t.withMutations((function(t){return t.set("isValidating",!1).set("isInvalid",!0).set("errorMessage",n)}))}function o(t,e){var n=e.authToken,r=e.host;return Fe({authToken:n,host:r})}function u(){return Ge.getInitialState()}function a(t,e){var n=e.rememberAuth;return n}function s(t){return t.withMutations((function(t){t.set("isStreaming",!0).set("hasError",!1)}))}function c(t){return t.withMutations((function(t){t.set("isStreaming",!1).set("hasError",!0)}))}function f(){return Xe.getInitialState()}function h(t){return{type:"auth",api_password:t}}function l(){return{type:"get_states"}}function p(){return{type:"get_config"}}function _(){return{type:"get_services"}}function d(){return{type:"get_panels"}}function v(t,e,n){var r={type:"call_service",domain:t,service:e};return n&&(r.service_data=n),r}function y(t){var e={type:"subscribe_events"};return t&&(e.event_type=t),e}function g(t){return{type:"unsubscribe_events",subscription:t}}function m(){return{type:"ping"}}function S(t,e){return{type:"result",success:!1,error:{code:t,message:e}}}function E(t){return t.result}function b(t,e){var n=new tn(t,e);return n.connect()}function I(t,e,n,r){void 0===r&&(r=null);var i=t.evaluate(Mo.authInfo),o=i.host+"/api/"+n;return new Promise(function(t,n){var u=new XMLHttpRequest;u.open(e,o,!0),u.setRequestHeader("X-HA-access",i.authToken),u.onload=function(){var e;try{e="application/json"===u.getResponseHeader("content-type")?JSON.parse(u.responseText):u.responseText}catch(t){e=u.responseText}u.status>199&&u.status<300?t(e):n(e)},u.onerror=function(){return n({})},r?(u.setRequestHeader("Content-Type","application/json;charset=UTF-8"),u.send(JSON.stringify(r))):u.send()})}function O(t,e){var n=e.model,r=e.result,i=e.params,o=n.entity;if(!r)return t;var u=i.replace?sn({}):t.get(o),a=Array.isArray(r)?r:[r],s=n.fromJSON||sn;return t.set(o,u.withMutations((function(t){for(var e=0;e6e4}function gt(t,e){var n=e.date;return n.toISOString()}function mt(){return Qr.getInitialState()}function St(t,e){var n=e.date,r=e.stateHistory;return 0===r.length?t.set(n,$r({})):t.withMutations((function(t){r.forEach((function(e){return t.setIn([n,e[0].entity_id],$r(e.map(In.fromJSON)))}))}))}function Et(){return ti.getInitialState()}function bt(t,e){var n=e.stateHistory;return t.withMutations((function(t){n.forEach((function(e){return t.set(e[0].entity_id,ii(e.map(In.fromJSON)))}))}))}function It(){return oi.getInitialState()}function Ot(t,e){var n=e.stateHistory,r=(new Date).getTime();return t.withMutations((function(t){n.forEach((function(e){return t.set(e[0].entity_id,r)})),history.length>1&&t.set(si,r)}))}function wt(){return ci.getInitialState()}function Tt(t,e){t.dispatch(Wr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function At(t,e){void 0===e&&(e=null),t.dispatch(Wr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),on(t,"GET",n).then((function(e){return t.dispatch(Wr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})}),(function(){return t.dispatch(Wr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})}))}function Ct(t,e){return t.dispatch(Wr.ENTITY_HISTORY_FETCH_START,{date:e}),on(t,"GET","history/period/"+e).then((function(n){return t.dispatch(Wr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})}),(function(){return t.dispatch(Wr.ENTITY_HISTORY_FETCH_ERROR,{})}))}function Dt(t){var e=t.evaluate(li);return Ct(t,e)}function zt(t){t.registerStores({currentEntityHistoryDate:Qr,entityHistory:ti,isLoadingEntityHistory:ni,recentEntityHistory:oi,recentEntityHistoryUpdated:ci})}function Rt(t){t.registerStores({moreInfoEntityId:Yr})}function Mt(t,e){var n=e.model,r=e.result,i=e.params;if(null===t||"entity"!==n.entity||!i.replace)return t;for(var o=0;o0?i=setTimeout(r,e-c):(i=null,n||(s=t.apply(u,o),i||(u=o=null)))}var i,o,u,a,s;null==e&&(e=100);var c=function(){u=this,o=arguments,a=(new Date).getTime();var c=n&&!i;return i||(i=setTimeout(r,e)),c&&(s=t.apply(u,o),u=o=null),s};return c.clear=function(){i&&(clearTimeout(i),i=null)},c}function Yt(t){var e=fo[t.hassId];e&&(e.scheduleHealthCheck.clear(),e.conn.close(),fo[t.hassId]=!1)}function Jt(t,e){void 0===e&&(e={});var n=e.syncOnInitialConnect;void 0===n&&(n=!0),Yt(t);var r=t.evaluate(Mo.authToken),i="https:"===document.location.protocol?"wss://":"ws://";i+=document.location.hostname,document.location.port&&(i+=":"+document.location.port),i+="/api/websocket",b(i,{authToken:r}).then((function(e){var r=Bt((function(){return e.ping()}),so);r(),e.socket.addEventListener("message",r),fo[t.hassId]={conn:e,scheduleHealthCheck:r},co.forEach((function(n){return e.subscribeEvents(ao.bind(null,t),n)})),t.batch((function(){t.dispatch(Ye.STREAM_START),n&&io.fetchAll(t)})),e.addEventListener("disconnected",(function(){t.dispatch(Ye.STREAM_ERROR)})),e.addEventListener("ready",(function(){t.batch((function(){t.dispatch(Ye.STREAM_START),io.fetchAll(t)}))}))}))}function Wt(t){t.registerStores({streamStatus:Xe})}function Xt(t,e,n){void 0===n&&(n={});var r=n.rememberAuth;void 0===r&&(r=!1);var i=n.host;void 0===i&&(i=""),t.dispatch(Ue.VALIDATING_AUTH_TOKEN,{authToken:e,host:i}),io.fetchAll(t).then((function(){t.dispatch(Ue.VALID_AUTH_TOKEN,{authToken:e,host:i,rememberAuth:r}),vo.start(t,{syncOnInitialConnect:!1})}),(function(e){void 0===e&&(e={});var n=e.message;void 0===n&&(n=mo),t.dispatch(Ue.INVALID_AUTH_TOKEN,{errorMessage:n})}))}function Qt(t){t.dispatch(Ue.LOG_OUT,{})}function Zt(t){t.registerStores({authAttempt:Ve,authCurrent:Ge,rememberAuth:Be})}function $t(){if(!("localStorage"in window))return{};var t=window.localStorage,e="___test";try{return t.setItem(e,e),t.removeItem(e),t}catch(t){return{}}}function te(){var t=new Uo({debug:!1});return t.hassId=Ho++,t}function ee(t,e,n){Object.keys(n).forEach((function(r){var i=n[r];if("register"in i&&i.register(e),"getters"in i&&Object.defineProperty(t,r+"Getters",{value:i.getters,enumerable:!0}),"actions"in i){var o={};Object.getOwnPropertyNames(i.actions).forEach((function(t){"function"==typeof i.actions[t]&&Object.defineProperty(o,t,{value:i.actions[t].bind(null,e),enumerable:!0})})),Object.defineProperty(t,r+"Actions",{value:o,enumerable:!0})}}))}function ne(t,e){return xo(t.attributes.entity_id.map((function(t){return e.get(t)})).filter((function(t){return!!t})))}function re(t){return on(t,"GET","error_log")}function ie(t,e){var n=e.date;return n.toISOString()}function oe(){return Jo.getInitialState()}function ue(t,e){var n=e.date,r=e.entries;return t.set(n,eu(r.map($o.fromJSON)))}function ae(){return nu.getInitialState()}function se(t,e){var n=e.date;return t.set(n,(new Date).getTime())}function ce(){return ou.getInitialState()}function fe(t,e){t.dispatch(Bo.LOGBOOK_DATE_SELECTED,{date:e})}function he(t,e){t.dispatch(Bo.LOGBOOK_ENTRIES_FETCH_START,{date:e}),on(t,"GET","logbook/"+e).then((function(n){return t.dispatch(Bo.LOGBOOK_ENTRIES_FETCH_SUCCESS,{date:e,entries:n})}),(function(){return t.dispatch(Bo.LOGBOOK_ENTRIES_FETCH_ERROR,{})}))}function le(t){return!t||(new Date).getTime()-t>su}function pe(t){t.registerStores({currentLogbookDate:Jo,isLoadingLogbookEntries:Xo,logbookEntries:nu,logbookEntriesUpdated:ou})}function _e(t){return t.set("active",!0)}function de(t){return t.set("active",!1)}function ve(){return Su.getInitialState()}function ye(t){return navigator.serviceWorker.getRegistration().then((function(t){if(!t)throw new Error("No service worker registered.");return t.pushManager.subscribe({userVisibleOnly:!0})})).then((function(e){var n;return n=navigator.userAgent.toLowerCase().indexOf("firefox")>-1?"firefox":"chrome",on(t,"POST","notify.html5",{subscription:e,browser:n}).then((function(){return t.dispatch(yu.PUSH_NOTIFICATIONS_SUBSCRIBE,{})})).then((function(){return!0}))})).catch((function(e){var n;return n=e.message&&e.message.indexOf("gcm_sender_id")!==-1?"Please setup the notify.html5 platform.":"Notification registration failed.",console.error(e),Vn.createNotification(t,n),!1}))}function ge(t){return navigator.serviceWorker.getRegistration().then((function(t){if(!t)throw new Error("No service worker registered");return t.pushManager.subscribe({userVisibleOnly:!0})})).then((function(e){return on(t,"DELETE","notify.html5",{subscription:e}).then((function(){return e.unsubscribe()})).then((function(){return t.dispatch(yu.PUSH_NOTIFICATIONS_UNSUBSCRIBE,{})})).then((function(){return!0}))})).catch((function(e){var n="Failed unsubscribing for push notifications.";return console.error(e),Vn.createNotification(t,n),!1}))}function me(t){t.registerStores({pushNotifications:Su})}function Se(t,e){return on(t,"POST","template",{template:e})}function Ee(t){return t.set("isListening",!0)}function be(t,e){var n=e.interimTranscript,r=e.finalTranscript;return t.withMutations((function(t){return t.set("isListening",!0).set("isTransmitting",!1).set("interimTranscript",n).set("finalTranscript",r)}))}function Ie(t,e){var n=e.finalTranscript;return t.withMutations((function(t){return t.set("isListening",!1).set("isTransmitting",!0).set("interimTranscript","").set("finalTranscript",n)}))}function Oe(){return Nu.getInitialState()}function we(){return Nu.getInitialState()}function Te(){return Nu.getInitialState()}function Ae(t){return Pu[t.hassId]}function Ce(t){var e=Ae(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(Lu.VOICE_TRANSMITTING,{finalTranscript:n}),tr.callService(t,"conversation","process",{text:n}).then((function(){t.dispatch(Lu.VOICE_DONE)}),(function(){t.dispatch(Lu.VOICE_ERROR)}))}}function De(t){var e=Ae(t);e&&(e.recognition.stop(),Pu[t.hassId]=!1)}function ze(t){Ce(t),De(t)}function Re(t){var e=ze.bind(null,t);e();var n=new webkitSpeechRecognition;Pu[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(Lu.VOICE_START)},n.onerror=function(){return t.dispatch(Lu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=Ae(t);if(n){for(var r="",i="",o=e.resultIndex;o>>0;if(""+n!==e||4294967295===n)return NaN;e=n}return e<0?_(t)+e:e}function v(){return!0}function y(t,e,n){return(0===t||void 0!==n&&t<=-n)&&(void 0===e||void 0!==n&&e>=n)}function g(t,e){return S(t,e,0)}function m(t,e){return S(t,e,e)}function S(t,e,n){return void 0===t?n:t<0?Math.max(0,e+t):void 0===e?t:Math.min(e,t)}function E(t){this.next=t}function b(t,e,n,r){var i=0===t?e:1===t?n:[e,n];return r?r.value=i:r={value:i,done:!1},r}function I(){return{value:void 0,done:!0}}function O(t){return!!A(t)}function w(t){return t&&"function"==typeof t.next}function T(t){var e=A(t);return e&&e.call(t)}function A(t){var e=t&&(In&&t[In]||t[On]);if("function"==typeof e)return e}function C(t){return t&&"number"==typeof t.length}function D(t){return null===t||void 0===t?U():o(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?U().toKeyedSeq():o(t)?u(t)?t.toSeq():t.fromEntrySeq():H(t)}function R(t){return null===t||void 0===t?U():o(t)?u(t)?t.entrySeq():t.toIndexedSeq():x(t)}function M(t){return(null===t||void 0===t?U():o(t)?u(t)?t.entrySeq():t:x(t)).toSetSeq()}function L(t){this._array=t,this.size=t.length}function j(t){var e=Object.keys(t);this._object=t,this._keys=e,this.size=e.length}function k(t){this._iterable=t,this.size=t.length||t.size}function N(t){this._iterator=t,this._iteratorCache=[]}function P(t){return!(!t||!t[Tn])}function U(){return An||(An=new L([]))}function H(t){var e=Array.isArray(t)?new L(t).fromEntrySeq():w(t)?new N(t).fromEntrySeq():O(t)?new k(t).fromEntrySeq():"object"==typeof t?new j(t):void 0;if(!e)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+t);return e}function x(t){var e=q(t);if(!e)throw new TypeError("Expected Array or iterable object of values: "+t);return e}function V(t){var e=q(t)||"object"==typeof t&&new j(t);if(!e)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+t);return e}function q(t){return C(t)?new L(t):w(t)?new N(t):O(t)?new k(t):void 0}function F(t,e,n,r){var i=t._cache;if(i){for(var o=i.length-1,u=0;u<=o;u++){var a=i[n?o-u:u];if(e(a[1],r?a[0]:u,t)===!1)return u+1}return u}return t.__iterateUncached(e,n)}function G(t,e,n,r){var i=t._cache;if(i){var o=i.length-1,u=0;return new E(function(){var t=i[n?o-u:u];return u++>o?I():b(e,r?t[0]:u-1,t[1])})}return t.__iteratorUncached(e,n)}function K(t,e){return e?B(e,t,"",{"":t}):Y(t)}function B(t,e,n,r){return Array.isArray(e)?t.call(r,n,R(e).map((function(n,r){return B(t,n,r,e)}))):J(e)?t.call(r,n,z(e).map((function(n,r){return B(t,n,r,e)}))):e}function Y(t){return Array.isArray(t)?R(t).map(Y).toList():J(t)?z(t).map(Y).toMap():t}function J(t){return t&&(t.constructor===Object||void 0===t.constructor)}function W(t,e){if(t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1;if("function"==typeof t.valueOf&&"function"==typeof e.valueOf){if(t=t.valueOf(),e=e.valueOf(),t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1}return!("function"!=typeof t.equals||"function"!=typeof e.equals||!t.equals(e))}function X(t,e){if(t===e)return!0;if(!o(e)||void 0!==t.size&&void 0!==e.size&&t.size!==e.size||void 0!==t.__hash&&void 0!==e.__hash&&t.__hash!==e.__hash||u(t)!==u(e)||a(t)!==a(e)||c(t)!==c(e))return!1;if(0===t.size&&0===e.size)return!0;var n=!s(t);if(c(t)){var r=t.entries();return e.every((function(t,e){var i=r.next().value;return i&&W(i[1],t)&&(n||W(i[0],e))}))&&r.next().done}var i=!1;if(void 0===t.size)if(void 0===e.size)"function"==typeof t.cacheResult&&t.cacheResult();else{i=!0;var f=t;t=e,e=f}var h=!0,l=e.__iterate((function(e,r){if(n?!t.has(e):i?!W(e,t.get(r,yn)):!W(t.get(r,yn),e))return h=!1,!1}));return h&&t.size===l}function Q(t,e){if(!(this instanceof Q))return new Q(t,e);if(this._value=t,this.size=void 0===e?1/0:Math.max(0,e),0===this.size){if(Cn)return Cn;Cn=this}}function Z(t,e){if(!t)throw new Error(e)}function $(t,e,n){if(!(this instanceof $))return new $(t,e,n);if(Z(0!==n,"Cannot step a Range by 0"),t=t||0,void 0===e&&(e=1/0),n=void 0===n?1:Math.abs(n),e>>1&1073741824|3221225471&t}function ot(t){if(t===!1||null===t||void 0===t)return 0;if("function"==typeof t.valueOf&&(t=t.valueOf(),t===!1||null===t||void 0===t))return 0;if(t===!0)return 1;var e=typeof t;if("number"===e){if(t!==t||t===1/0)return 0;var n=0|t;for(n!==t&&(n^=4294967295*t);t>4294967295;)t/=4294967295,n^=t;return it(n)}if("string"===e)return t.length>Pn?ut(t):at(t);if("function"==typeof t.hashCode)return t.hashCode();if("object"===e)return st(t);if("function"==typeof t.toString)return at(t.toString());throw new Error("Value type "+e+" cannot be hashed.")}function ut(t){var e=xn[t];return void 0===e&&(e=at(t),Hn===Un&&(Hn=0,xn={}),Hn++,xn[t]=e),e}function at(t){for(var e=0,n=0;n0)switch(t.nodeType){case 1:return t.uniqueID;case 9:return t.documentElement&&t.documentElement.uniqueID}}function ft(t){Z(t!==1/0,"Cannot perform this action with an infinite size.")}function ht(t){return null===t||void 0===t?bt():lt(t)&&!c(t)?t:bt().withMutations((function(e){var r=n(t);ft(r.size),r.forEach((function(t,n){return e.set(n,t)}))}))}function lt(t){return!(!t||!t[Vn])}function pt(t,e){this.ownerID=t,this.entries=e}function _t(t,e,n){this.ownerID=t,this.bitmap=e,this.nodes=n}function dt(t,e,n){this.ownerID=t,this.count=e,this.nodes=n}function vt(t,e,n){this.ownerID=t,this.keyHash=e,this.entries=n}function yt(t,e,n){this.ownerID=t,this.keyHash=e,this.entry=n}function gt(t,e,n){this._type=e,this._reverse=n,this._stack=t._root&&St(t._root)}function mt(t,e){return b(t,e[0],e[1])}function St(t,e){return{node:t,index:0,__prev:e}}function Et(t,e,n,r){var i=Object.create(qn);return i.size=t,i._root=e,i.__ownerID=n,i.__hash=r,i.__altered=!1,i}function bt(){return Fn||(Fn=Et(0))}function It(t,e,n){var r,i;if(t._root){var o=f(gn),u=f(mn);if(r=Ot(t._root,t.__ownerID,0,void 0,e,n,o,u),!u.value)return t;i=t.size+(o.value?n===yn?-1:1:0)}else{if(n===yn)return t;i=1,r=new pt(t.__ownerID,[[e,n]])}return t.__ownerID?(t.size=i,t._root=r,t.__hash=void 0,t.__altered=!0,t):r?Et(i,r):bt()}function Ot(t,e,n,r,i,o,u,a){return t?t.update(e,n,r,i,o,u,a):o===yn?t:(h(a),h(u),new yt(e,r,[i,o]))}function wt(t){return t.constructor===yt||t.constructor===vt}function Tt(t,e,n,r,i){if(t.keyHash===r)return new vt(e,r,[t.entry,i]);var o,u=(0===n?t.keyHash:t.keyHash>>>n)&vn,a=(0===n?r:r>>>n)&vn,s=u===a?[Tt(t,e,n+_n,r,i)]:(o=new yt(e,r,i),u>>=1)u[a]=1&n?e[o++]:void 0;return u[r]=i,new dt(t,o+1,u)}function zt(t,e,r){for(var i=[],u=0;u>1&1431655765,t=(858993459&t)+(t>>2&858993459),t=t+(t>>4)&252645135,t+=t>>8,t+=t>>16,127&t}function Nt(t,e,n,r){var i=r?t:p(t);return i[e]=n,i}function Pt(t,e,n,r){var i=t.length+1;if(r&&e+1===i)return t[e]=n,t;for(var o=new Array(i),u=0,a=0;a0&&io?0:o-n,c=u-n;return c>dn&&(c=dn),function(){if(i===c)return Xn;var t=e?--c:i++;return r&&r[t]}}function i(t,r,i){var a,s=t&&t.array,c=i>o?0:o-i>>r,f=(u-i>>r)+1;return f>dn&&(f=dn),function(){for(;;){if(a){var t=a();if(t!==Xn)return t;a=null}if(c===f)return Xn;var o=e?--f:c++;a=n(s&&s[o],r-_n,i+(o<=t.size||e<0)return t.withMutations((function(t){e<0?Wt(t,e).set(0,n):Wt(t,0,e+1).set(e,n)}));e+=t._origin;var r=t._tail,i=t._root,o=f(mn);return e>=Qt(t._capacity)?r=Bt(r,t.__ownerID,0,e,n,o):i=Bt(i,t.__ownerID,t._level,e,n,o),o.value?t.__ownerID?(t._root=i,t._tail=r,t.__hash=void 0,t.__altered=!0,t):Ft(t._origin,t._capacity,t._level,i,r):t}function Bt(t,e,n,r,i,o){var u=r>>>n&vn,a=t&&u0){var c=t&&t.array[u],f=Bt(c,e,n-_n,r,i,o);return f===c?t:(s=Yt(t,e),s.array[u]=f,s)}return a&&t.array[u]===i?t:(h(o),s=Yt(t,e),void 0===i&&u===s.array.length-1?s.array.pop():s.array[u]=i,s)}function Yt(t,e){return e&&t&&e===t.ownerID?t:new Vt(t?t.array.slice():[],e)}function Jt(t,e){if(e>=Qt(t._capacity))return t._tail;if(e<1<0;)n=n.array[e>>>r&vn],r-=_n;return n}}function Wt(t,e,n){void 0!==e&&(e|=0),void 0!==n&&(n|=0);var r=t.__ownerID||new l,i=t._origin,o=t._capacity,u=i+e,a=void 0===n?o:n<0?o+n:i+n;if(u===i&&a===o)return t;if(u>=a)return t.clear();for(var s=t._level,c=t._root,f=0;u+f<0;)c=new Vt(c&&c.array.length?[void 0,c]:[],r),s+=_n,f+=1<=1<h?new Vt([],r):_;if(_&&p>h&&u_n;y-=_n){var g=h>>>y&vn;v=v.array[g]=Yt(v.array[g],r)}v.array[h>>>_n&vn]=_}if(a=p)u-=p,a-=p,s=_n,c=null,d=d&&d.removeBefore(r,0,u);else if(u>i||p>>s&vn;if(m!==p>>>s&vn)break;m&&(f+=(1<i&&(c=c.removeBefore(r,s,u-f)),c&&pu&&(u=c.size),o(s)||(c=c.map((function(t){return K(t)}))),i.push(c)}return u>t.size&&(t=t.setSize(u)),Lt(t,e,i)}function Qt(t){return t>>_n<<_n}function Zt(t){return null===t||void 0===t?ee():$t(t)?t:ee().withMutations((function(e){var r=n(t);ft(r.size),r.forEach((function(t,n){return e.set(n,t)}))}))}function $t(t){return lt(t)&&c(t)}function te(t,e,n,r){var i=Object.create(Zt.prototype);return i.size=t?t.size:0,i._map=t,i._list=e,i.__ownerID=n,i.__hash=r,i}function ee(){return Qn||(Qn=te(bt(),Gt()))}function ne(t,e,n){var r,i,o=t._map,u=t._list,a=o.get(e),s=void 0!==a;if(n===yn){if(!s)return t;u.size>=dn&&u.size>=2*o.size?(i=u.filter((function(t,e){return void 0!==t&&a!==e})),r=i.toKeyedSeq().map((function(t){return t[0]})).flip().toMap(),t.__ownerID&&(r.__ownerID=i.__ownerID=t.__ownerID)):(r=o.remove(e),i=a===u.size-1?u.pop():u.set(a,void 0))}else if(s){if(n===u.get(a)[1])return t;r=o,i=u.set(a,[e,n])}else r=o.set(e,u.size),i=u.set(u.size,[e,n]);return t.__ownerID?(t.size=r.size,t._map=r,t._list=i,t.__hash=void 0,t):te(r,i)}function re(t,e){this._iter=t,this._useKeys=e,this.size=t.size}function ie(t){this._iter=t,this.size=t.size}function oe(t){this._iter=t,this.size=t.size}function ue(t){this._iter=t,this.size=t.size}function ae(t){var e=Ce(t);return e._iter=t,e.size=t.size,e.flip=function(){return t},e.reverse=function(){var e=t.reverse.apply(this);return e.flip=function(){return t.reverse()},e},e.has=function(e){return t.includes(e)},e.includes=function(e){return t.has(e)},e.cacheResult=De,e.__iterateUncached=function(e,n){var r=this;return t.__iterate((function(t,n){return e(n,t,r)!==!1}),n)},e.__iteratorUncached=function(e,n){if(e===bn){var r=t.__iterator(e,n);return new E(function(){var t=r.next();if(!t.done){var e=t.value[0];t.value[0]=t.value[1],t.value[1]=e}return t})}return t.__iterator(e===En?Sn:En,n)},e}function se(t,e,n){var r=Ce(t);return r.size=t.size,r.has=function(e){return t.has(e)},r.get=function(r,i){var o=t.get(r,yn);return o===yn?i:e.call(n,o,r,t)},r.__iterateUncached=function(r,i){var o=this;return t.__iterate((function(t,i,u){return r(e.call(n,t,i,u),i,o)!==!1}),i)},r.__iteratorUncached=function(r,i){var o=t.__iterator(bn,i);return new E(function(){var i=o.next();if(i.done)return i;var u=i.value,a=u[0];return b(r,a,e.call(n,u[1],a,t),i)})},r}function ce(t,e){var n=Ce(t);return n._iter=t,n.size=t.size,n.reverse=function(){return t},t.flip&&(n.flip=function(){var e=ae(t);return e.reverse=function(){return t.flip()},e}),n.get=function(n,r){return t.get(e?n:-1-n,r)},n.has=function(n){return t.has(e?n:-1-n)},n.includes=function(e){return t.includes(e)},n.cacheResult=De,n.__iterate=function(e,n){var r=this;return t.__iterate((function(t,n){return e(t,n,r)}),!n)},n.__iterator=function(e,n){return t.__iterator(e,!n)},n}function fe(t,e,n,r){var i=Ce(t);return r&&(i.has=function(r){var i=t.get(r,yn);return i!==yn&&!!e.call(n,i,r,t)},i.get=function(r,i){var o=t.get(r,yn);return o!==yn&&e.call(n,o,r,t)?o:i}),i.__iterateUncached=function(i,o){var u=this,a=0;return t.__iterate((function(t,o,s){if(e.call(n,t,o,s))return a++,i(t,r?o:a-1,u)}),o),a},i.__iteratorUncached=function(i,o){var u=t.__iterator(bn,o),a=0;return new E(function(){for(;;){var o=u.next();if(o.done)return o;var s=o.value,c=s[0],f=s[1];if(e.call(n,f,c,t))return b(i,r?c:a++,f,o)}})},i}function he(t,e,n){var r=ht().asMutable();return t.__iterate((function(i,o){r.update(e.call(n,i,o,t),0,(function(t){return t+1}))})),r.asImmutable()}function le(t,e,n){var r=u(t),i=(c(t)?Zt():ht()).asMutable();t.__iterate((function(o,u){i.update(e.call(n,o,u,t),(function(t){return t=t||[],t.push(r?[u,o]:o),t}))}));var o=Ae(t);return i.map((function(e){return Oe(t,o(e))}))}function pe(t,e,n,r){var i=t.size;if(void 0!==e&&(e|=0),void 0!==n&&(n===1/0?n=i:n|=0),y(e,n,i))return t;var o=g(e,i),u=m(n,i);if(o!==o||u!==u)return pe(t.toSeq().cacheResult(),e,n,r);var a,s=u-o;s===s&&(a=s<0?0:s);var c=Ce(t);return c.size=0===a?a:t.size&&a||void 0,!r&&P(t)&&a>=0&&(c.get=function(e,n){return e=d(this,e),e>=0&&ea)return I();var t=i.next();return r||e===En?t:e===Sn?b(e,s-1,void 0,t):b(e,s-1,t.value[1],t)})},c}function _e(t,e,n){var r=Ce(t);return r.__iterateUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterate(r,i);var u=0;return t.__iterate((function(t,i,a){return e.call(n,t,i,a)&&++u&&r(t,i,o)})),u},r.__iteratorUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterator(r,i);var u=t.__iterator(bn,i),a=!0;return new E(function(){if(!a)return I();var t=u.next();if(t.done)return t;var i=t.value,s=i[0],c=i[1];return e.call(n,c,s,o)?r===bn?t:b(r,s,c,t):(a=!1,I())})},r}function de(t,e,n,r){var i=Ce(t);return i.__iterateUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterate(i,o);var a=!0,s=0;return t.__iterate((function(t,o,c){if(!a||!(a=e.call(n,t,o,c)))return s++,i(t,r?o:s-1,u)})),s},i.__iteratorUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterator(i,o);var a=t.__iterator(bn,o),s=!0,c=0;return new E(function(){var t,o,f;do{if(t=a.next(),t.done)return r||i===En?t:i===Sn?b(i,c++,void 0,t):b(i,c++,t.value[1],t);var h=t.value;o=h[0],f=h[1],s&&(s=e.call(n,f,o,u))}while(s);return i===bn?t:b(i,o,f,t)})},i}function ve(t,e){var r=u(t),i=[t].concat(e).map((function(t){return o(t)?r&&(t=n(t)):t=r?H(t):x(Array.isArray(t)?t:[t]),t})).filter((function(t){return 0!==t.size}));if(0===i.length)return t;if(1===i.length){var s=i[0];if(s===t||r&&u(s)||a(t)&&a(s))return s}var c=new L(i);return r?c=c.toKeyedSeq():a(t)||(c=c.toSetSeq()),c=c.flatten(!0),c.size=i.reduce((function(t,e){if(void 0!==t){var n=e.size;if(void 0!==n)return t+n}}),0),c}function ye(t,e,n){var r=Ce(t);return r.__iterateUncached=function(r,i){function u(t,c){var f=this;t.__iterate((function(t,i){return(!e||c0}function Ie(t,n,r){var i=Ce(t);return i.size=new L(r).map((function(t){return t.size})).min(),i.__iterate=function(t,e){for(var n,r=this,i=this.__iterator(En,e),o=0;!(n=i.next()).done&&t(n.value,o++,r)!==!1;);return o},i.__iteratorUncached=function(t,i){var o=r.map((function(t){return t=e(t),T(i?t.reverse():t)})),u=0,a=!1;return new E(function(){var e;return a||(e=o.map((function(t){return t.next()})),a=e.some((function(t){return t.done}))),a?I():b(t,u++,n.apply(null,e.map((function(t){return t.value}))))})},i}function Oe(t,e){return P(t)?e:t.constructor(e)}function we(t){if(t!==Object(t))throw new TypeError("Expected [K, V] tuple: "+t)}function Te(t){return ft(t.size),_(t)}function Ae(t){return u(t)?n:a(t)?r:i}function Ce(t){return Object.create((u(t)?z:a(t)?R:M).prototype)}function De(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):D.prototype.cacheResult.call(this)}function ze(t,e){return t>e?1:te?-1:0}function on(t){if(t.size===1/0)return 0;var e=c(t),n=u(t),r=e?1:0,i=t.__iterate(n?e?function(t,e){r=31*r+an(ot(t),ot(e))|0}:function(t,e){r=r+an(ot(t),ot(e))|0}:e?function(t){r=31*r+ot(t)|0}:function(t){r=r+ot(t)|0});return un(i,r)}function un(t,e){return e=Rn(e,3432918353),e=Rn(e<<15|e>>>-15,461845907),e=Rn(e<<13|e>>>-13,5),e=(e+3864292196|0)^t,e=Rn(e^e>>>16,2246822507),e=Rn(e^e>>>13,3266489909),e=it(e^e>>>16)}function an(t,e){return t^e+2654435769+(t<<6)+(t>>2)|0}var sn=Array.prototype.slice;t(n,e),t(r,e),t(i,e),e.isIterable=o,e.isKeyed=u,e.isIndexed=a,e.isAssociative=s,e.isOrdered=c,e.Keyed=n,e.Indexed=r,e.Set=i;var cn="@@__IMMUTABLE_ITERABLE__@@",fn="@@__IMMUTABLE_KEYED__@@",hn="@@__IMMUTABLE_INDEXED__@@",ln="@@__IMMUTABLE_ORDERED__@@",pn="delete",_n=5,dn=1<<_n,vn=dn-1,yn={},gn={value:!1},mn={value:!1},Sn=0,En=1,bn=2,In="function"==typeof Symbol&&Symbol.iterator,On="@@iterator",wn=In||On;E.prototype.toString=function(){return"[Iterator]"},E.KEYS=Sn,E.VALUES=En,E.ENTRIES=bn,E.prototype.inspect=E.prototype.toSource=function(){return this.toString()},E.prototype[wn]=function(){return this},t(D,e),D.of=function(){return D(arguments)},D.prototype.toSeq=function(){return this},D.prototype.toString=function(){return this.__toString("Seq {","}")},D.prototype.cacheResult=function(){return!this._cache&&this.__iterateUncached&&(this._cache=this.entrySeq().toArray(),this.size=this._cache.length),this},D.prototype.__iterate=function(t,e){return F(this,t,e,!0)},D.prototype.__iterator=function(t,e){return G(this,t,e,!0)},t(z,D),z.prototype.toKeyedSeq=function(){return this},t(R,D),R.of=function(){return R(arguments)},R.prototype.toIndexedSeq=function(){return this},R.prototype.toString=function(){return this.__toString("Seq [","]")},R.prototype.__iterate=function(t,e){return F(this,t,e,!1)},R.prototype.__iterator=function(t,e){return G(this,t,e,!1)},t(M,D),M.of=function(){return M(arguments)},M.prototype.toSetSeq=function(){return this},D.isSeq=P,D.Keyed=z,D.Set=M,D.Indexed=R;var Tn="@@__IMMUTABLE_SEQ__@@";D.prototype[Tn]=!0,t(L,R),L.prototype.get=function(t,e){return this.has(t)?this._array[d(this,t)]:e},L.prototype.__iterate=function(t,e){for(var n=this,r=this._array,i=r.length-1,o=0;o<=i;o++)if(t(r[e?i-o:o],o,n)===!1)return o+1;return o},L.prototype.__iterator=function(t,e){var n=this._array,r=n.length-1,i=0;return new E(function(){return i>r?I():b(t,i,n[e?r-i++:i++])})},t(j,z),j.prototype.get=function(t,e){return void 0===e||this.has(t)?this._object[t]:e},j.prototype.has=function(t){return this._object.hasOwnProperty(t)},j.prototype.__iterate=function(t,e){for(var n=this,r=this._object,i=this._keys,o=i.length-1,u=0;u<=o;u++){var a=i[e?o-u:u];if(t(r[a],a,n)===!1)return u+1}return u},j.prototype.__iterator=function(t,e){var n=this._object,r=this._keys,i=r.length-1,o=0;return new E(function(){var u=r[e?i-o:o];return o++>i?I():b(t,u,n[u])})},j.prototype[ln]=!0,t(k,R),k.prototype.__iterateUncached=function(t,e){var n=this;if(e)return this.cacheResult().__iterate(t,e);var r=this._iterable,i=T(r),o=0;if(w(i))for(var u;!(u=i.next()).done&&t(u.value,o++,n)!==!1;);return o},k.prototype.__iteratorUncached=function(t,e){if(e)return this.cacheResult().__iterator(t,e);var n=this._iterable,r=T(n);if(!w(r))return new E(I);var i=0;return new E(function(){var e=r.next();return e.done?e:b(t,i++,e.value)})},t(N,R),N.prototype.__iterateUncached=function(t,e){var n=this;if(e)return this.cacheResult().__iterate(t,e);for(var r=this._iterator,i=this._iteratorCache,o=0;o=r.length){var e=n.next();if(e.done)return e;r[i]=e.value}return b(t,i,r[i++])})};var An;t(Q,R),Q.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},Q.prototype.get=function(t,e){return this.has(t)?this._value:e},Q.prototype.includes=function(t){return W(this._value,t)},Q.prototype.slice=function(t,e){var n=this.size;return y(t,e,n)?this:new Q(this._value,m(e,n)-g(t,n))},Q.prototype.reverse=function(){return this},Q.prototype.indexOf=function(t){return W(this._value,t)?0:-1},Q.prototype.lastIndexOf=function(t){return W(this._value,t)?this.size:-1},Q.prototype.__iterate=function(t,e){for(var n=this,r=0;r=0&&e=0&&nn?I():b(t,o++,u)})},$.prototype.equals=function(t){return t instanceof $?this._start===t._start&&this._end===t._end&&this._step===t._step:X(this,t)};var Dn;t(tt,e),t(et,tt),t(nt,tt),t(rt,tt),tt.Keyed=et,tt.Indexed=nt,tt.Set=rt;var zn,Rn="function"==typeof Math.imul&&Math.imul(4294967295,2)===-2?Math.imul:function(t,e){t|=0,e|=0;var n=65535&t,r=65535&e;return n*r+((t>>>16)*r+n*(e>>>16)<<16>>>0)|0},Mn=Object.isExtensible,Ln=(function(){try{return Object.defineProperty({},"@",{}),!0}catch(t){return!1}})(),jn="function"==typeof WeakMap;jn&&(zn=new WeakMap);var kn=0,Nn="__immutablehash__";"function"==typeof Symbol&&(Nn=Symbol(Nn));var Pn=16,Un=255,Hn=0,xn={};t(ht,et),ht.of=function(){var t=sn.call(arguments,0);return bt().withMutations((function(e){for(var n=0;n=t.length)throw new Error("Missing value for key: "+t[n]);e.set(t[n],t[n+1])}}))},ht.prototype.toString=function(){return this.__toString("Map {","}")},ht.prototype.get=function(t,e){return this._root?this._root.get(0,void 0,t,e):e},ht.prototype.set=function(t,e){return It(this,t,e)},ht.prototype.setIn=function(t,e){return this.updateIn(t,yn,(function(){return e}))},ht.prototype.remove=function(t){return It(this,t,yn)},ht.prototype.deleteIn=function(t){return this.updateIn(t,(function(){return yn}))},ht.prototype.update=function(t,e,n){return 1===arguments.length?t(this):this.updateIn([t],e,n)},ht.prototype.updateIn=function(t,e,n){n||(n=e,e=void 0);var r=jt(this,Re(t),e,n);return r===yn?void 0:r},ht.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):bt()},ht.prototype.merge=function(){return zt(this,void 0,arguments)},ht.prototype.mergeWith=function(t){var e=sn.call(arguments,1);return zt(this,t,e)},ht.prototype.mergeIn=function(t){var e=sn.call(arguments,1);return this.updateIn(t,bt(),(function(t){return"function"==typeof t.merge?t.merge.apply(t,e):e[e.length-1]}))},ht.prototype.mergeDeep=function(){return zt(this,Rt,arguments)},ht.prototype.mergeDeepWith=function(t){var e=sn.call(arguments,1);return zt(this,Mt(t),e)},ht.prototype.mergeDeepIn=function(t){var e=sn.call(arguments,1);return this.updateIn(t,bt(),(function(t){return"function"==typeof t.mergeDeep?t.mergeDeep.apply(t,e):e[e.length-1]}))},ht.prototype.sort=function(t){return Zt(Se(this,t))},ht.prototype.sortBy=function(t,e){return Zt(Se(this,e,t))},ht.prototype.withMutations=function(t){var e=this.asMutable();return t(e),e.wasAltered()?e.__ensureOwner(this.__ownerID):this},ht.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new l)},ht.prototype.asImmutable=function(){return this.__ensureOwner()},ht.prototype.wasAltered=function(){return this.__altered},ht.prototype.__iterator=function(t,e){return new gt(this,t,e)},ht.prototype.__iterate=function(t,e){var n=this,r=0;return this._root&&this._root.iterate((function(e){return r++,t(e[1],e[0],n)}),e),r},ht.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Et(this.size,this._root,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},ht.isMap=lt;var Vn="@@__IMMUTABLE_MAP__@@",qn=ht.prototype;qn[Vn]=!0,qn[pn]=qn.remove,qn.removeIn=qn.deleteIn,pt.prototype.get=function(t,e,n,r){for(var i=this.entries,o=0,u=i.length;o=Gn)return At(t,s,r,i);var _=t&&t===this.ownerID,d=_?s:p(s);return l?a?c===f-1?d.pop():d[c]=d.pop():d[c]=[r,i]:d.push([r,i]),_?(this.entries=d,this):new pt(t,d)}},_t.prototype.get=function(t,e,n,r){void 0===e&&(e=ot(n));var i=1<<((0===t?e:e>>>t)&vn),o=this.bitmap;return 0===(o&i)?r:this.nodes[kt(o&i-1)].get(t+_n,e,n,r)},_t.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=ot(r));var a=(0===e?n:n>>>e)&vn,s=1<=Kn)return Dt(t,l,c,a,_);if(f&&!_&&2===l.length&&wt(l[1^h]))return l[1^h];if(f&&_&&1===l.length&&wt(_))return _;var d=t&&t===this.ownerID,v=f?_?c:c^s:c|s,y=f?_?Nt(l,h,_,d):Ut(l,h,d):Pt(l,h,_,d);return d?(this.bitmap=v,this.nodes=y,this):new _t(t,v,y)},dt.prototype.get=function(t,e,n,r){void 0===e&&(e=ot(n));var i=(0===t?e:e>>>t)&vn,o=this.nodes[i];return o?o.get(t+_n,e,n,r):r},dt.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=ot(r));var a=(0===e?n:n>>>e)&vn,s=i===yn,c=this.nodes,f=c[a];if(s&&!f)return this;var h=Ot(f,t,e+_n,n,r,i,o,u);if(h===f)return this;var l=this.count;if(f){if(!h&&(l--,l=0&&t>>e&vn;if(r>=this.array.length)return new Vt([],t);var i,o=0===r;if(e>0){var u=this.array[r];if(i=u&&u.removeBefore(t,e-_n,n),i===u&&o)return this}if(o&&!i)return this;var a=Yt(this,t);if(!o)for(var s=0;s>>e&vn;if(r>=this.array.length)return this;var i;if(e>0){var o=this.array[r];if(i=o&&o.removeAfter(t,e-_n,n),i===o&&r===this.array.length-1)return this}var u=Yt(this,t);return u.array.splice(r+1),i&&(u.array[r]=i),u};var Wn,Xn={};t(Zt,ht),Zt.of=function(){return this(arguments)},Zt.prototype.toString=function(){return this.__toString("OrderedMap {","}")},Zt.prototype.get=function(t,e){var n=this._map.get(t);return void 0!==n?this._list.get(n)[1]:e},Zt.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._map.clear(),this._list.clear(),this):ee()},Zt.prototype.set=function(t,e){return ne(this,t,e)},Zt.prototype.remove=function(t){return ne(this,t,yn)},Zt.prototype.wasAltered=function(){return this._map.wasAltered()||this._list.wasAltered()},Zt.prototype.__iterate=function(t,e){var n=this;return this._list.__iterate((function(e){return e&&t(e[1],e[0],n)}),e)},Zt.prototype.__iterator=function(t,e){return this._list.fromEntrySeq().__iterator(t,e)},Zt.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map.__ensureOwner(t),n=this._list.__ensureOwner(t);return t?te(e,n,t,this.__hash):(this.__ownerID=t,this._map=e,this._list=n,this)},Zt.isOrderedMap=$t,Zt.prototype[ln]=!0,Zt.prototype[pn]=Zt.prototype.remove;var Qn;t(re,z),re.prototype.get=function(t,e){return this._iter.get(t,e)},re.prototype.has=function(t){return this._iter.has(t)},re.prototype.valueSeq=function(){return this._iter.valueSeq()},re.prototype.reverse=function(){var t=this,e=ce(this,!0);return this._useKeys||(e.valueSeq=function(){return t._iter.toSeq().reverse()}),e},re.prototype.map=function(t,e){var n=this,r=se(this,t,e);return this._useKeys||(r.valueSeq=function(){return n._iter.toSeq().map(t,e)}),r},re.prototype.__iterate=function(t,e){var n,r=this;return this._iter.__iterate(this._useKeys?function(e,n){return t(e,n,r)}:(n=e?Te(this):0,function(i){return t(i,e?--n:n++,r)}),e)},re.prototype.__iterator=function(t,e){if(this._useKeys)return this._iter.__iterator(t,e);var n=this._iter.__iterator(En,e),r=e?Te(this):0;return new E(function(){var i=n.next();return i.done?i:b(t,e?--r:r++,i.value,i)})},re.prototype[ln]=!0,t(ie,R),ie.prototype.includes=function(t){return this._iter.includes(t)},ie.prototype.__iterate=function(t,e){var n=this,r=0;return this._iter.__iterate((function(e){return t(e,r++,n)}),e)},ie.prototype.__iterator=function(t,e){var n=this._iter.__iterator(En,e),r=0;return new E(function(){var e=n.next();return e.done?e:b(t,r++,e.value,e)})},t(oe,M),oe.prototype.has=function(t){return this._iter.includes(t)},oe.prototype.__iterate=function(t,e){var n=this;return this._iter.__iterate((function(e){return t(e,e,n)}),e)},oe.prototype.__iterator=function(t,e){var n=this._iter.__iterator(En,e);return new E(function(){var e=n.next();return e.done?e:b(t,e.value,e.value,e)})},t(ue,z),ue.prototype.entrySeq=function(){return this._iter.toSeq()},ue.prototype.__iterate=function(t,e){var n=this;return this._iter.__iterate((function(e){if(e){we(e);var r=o(e);return t(r?e.get(1):e[1],r?e.get(0):e[0],n)}}),e)},ue.prototype.__iterator=function(t,e){var n=this._iter.__iterator(En,e);return new E(function(){for(;;){var e=n.next();if(e.done)return e;var r=e.value;if(r){we(r);var i=o(r);return b(t,i?r.get(0):r[0],i?r.get(1):r[1],e)}}})},ie.prototype.cacheResult=re.prototype.cacheResult=oe.prototype.cacheResult=ue.prototype.cacheResult=De,t(Me,et),Me.prototype.toString=function(){return this.__toString(je(this)+" {","}")},Me.prototype.has=function(t){return this._defaultValues.hasOwnProperty(t)},Me.prototype.get=function(t,e){if(!this.has(t))return e;var n=this._defaultValues[t];return this._map?this._map.get(t,n):n},Me.prototype.clear=function(){if(this.__ownerID)return this._map&&this._map.clear(),this;var t=this.constructor;return t._empty||(t._empty=Le(this,bt()))},Me.prototype.set=function(t,e){if(!this.has(t))throw new Error('Cannot set unknown key "'+t+'" on '+je(this));if(this._map&&!this._map.has(t)){var n=this._defaultValues[t];if(e===n)return this}var r=this._map&&this._map.set(t,e);return this.__ownerID||r===this._map?this:Le(this,r)},Me.prototype.remove=function(t){if(!this.has(t))return this;var e=this._map&&this._map.remove(t);return this.__ownerID||e===this._map?this:Le(this,e)},Me.prototype.wasAltered=function(){return this._map.wasAltered()},Me.prototype.__iterator=function(t,e){var r=this;return n(this._defaultValues).map((function(t,e){return r.get(e)})).__iterator(t,e)},Me.prototype.__iterate=function(t,e){var r=this;return n(this._defaultValues).map((function(t,e){return r.get(e)})).__iterate(t,e)},Me.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map&&this._map.__ensureOwner(t);return t?Le(this,e,t):(this.__ownerID=t,this._map=e,this)};var Zn=Me.prototype;Zn[pn]=Zn.remove,Zn.deleteIn=Zn.removeIn=qn.removeIn,Zn.merge=qn.merge,Zn.mergeWith=qn.mergeWith,Zn.mergeIn=qn.mergeIn,Zn.mergeDeep=qn.mergeDeep,Zn.mergeDeepWith=qn.mergeDeepWith,Zn.mergeDeepIn=qn.mergeDeepIn,Zn.setIn=qn.setIn,Zn.update=qn.update,Zn.updateIn=qn.updateIn,Zn.withMutations=qn.withMutations,Zn.asMutable=qn.asMutable,Zn.asImmutable=qn.asImmutable,t(Pe,rt),Pe.of=function(){return this(arguments)},Pe.fromKeys=function(t){return this(n(t).keySeq())},Pe.prototype.toString=function(){return this.__toString("Set {","}")},Pe.prototype.has=function(t){return this._map.has(t)},Pe.prototype.add=function(t){ -return He(this,this._map.set(t,!0))},Pe.prototype.remove=function(t){return He(this,this._map.remove(t))},Pe.prototype.clear=function(){return He(this,this._map.clear())},Pe.prototype.union=function(){var t=sn.call(arguments,0);return t=t.filter((function(t){return 0!==t.size})),0===t.length?this:0!==this.size||this.__ownerID||1!==t.length?this.withMutations((function(e){for(var n=0;n=0;r--)n={value:t[r],next:n};return this.__ownerID?(this.size=e,this._head=n,this.__hash=void 0,this.__altered=!0,this):Je(e,n)},Be.prototype.pushAll=function(t){if(t=r(t),0===t.size)return this;ft(t.size);var e=this.size,n=this._head;return t.reverse().forEach((function(t){e++,n={value:t,next:n}})),this.__ownerID?(this.size=e,this._head=n,this.__hash=void 0,this.__altered=!0,this):Je(e,n)},Be.prototype.pop=function(){return this.slice(1)},Be.prototype.unshift=function(){return this.push.apply(this,arguments)},Be.prototype.unshiftAll=function(t){return this.pushAll(t)},Be.prototype.shift=function(){return this.pop.apply(this,arguments)},Be.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):We()},Be.prototype.slice=function(t,e){if(y(t,e,this.size))return this;var n=g(t,this.size),r=m(e,this.size);if(r!==this.size)return nt.prototype.slice.call(this,t,e);for(var i=this.size-n,o=this._head;n--;)o=o.next;return this.__ownerID?(this.size=i,this._head=o,this.__hash=void 0,this.__altered=!0,this):Je(i,o)},Be.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Je(this.size,this._head,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},Be.prototype.__iterate=function(t,e){var n=this;if(e)return this.reverse().__iterate(t);for(var r=0,i=this._head;i&&t(i.value,r++,n)!==!1;)i=i.next;return r},Be.prototype.__iterator=function(t,e){if(e)return this.reverse().__iterator(t);var n=0,r=this._head;return new E(function(){if(r){var e=r.value;return r=r.next,b(t,n++,e)}return I()})},Be.isStack=Ye;var ir="@@__IMMUTABLE_STACK__@@",or=Be.prototype;or[ir]=!0,or.withMutations=qn.withMutations,or.asMutable=qn.asMutable,or.asImmutable=qn.asImmutable,or.wasAltered=qn.wasAltered;var ur;e.Iterator=E,Xe(e,{toArray:function(){ft(this.size);var t=new Array(this.size||0);return this.valueSeq().__iterate((function(e,n){t[n]=e})),t},toIndexedSeq:function(){return new ie(this)},toJS:function(){return this.toSeq().map((function(t){return t&&"function"==typeof t.toJS?t.toJS():t})).__toJS()},toJSON:function(){return this.toSeq().map((function(t){return t&&"function"==typeof t.toJSON?t.toJSON():t})).__toJS()},toKeyedSeq:function(){return new re(this,!0)},toMap:function(){return ht(this.toKeyedSeq())},toObject:function(){ft(this.size);var t={};return this.__iterate((function(e,n){t[n]=e})),t},toOrderedMap:function(){return Zt(this.toKeyedSeq())},toOrderedSet:function(){return qe(u(this)?this.valueSeq():this)},toSet:function(){return Pe(u(this)?this.valueSeq():this)},toSetSeq:function(){return new oe(this)},toSeq:function(){return a(this)?this.toIndexedSeq():u(this)?this.toKeyedSeq():this.toSetSeq()},toStack:function(){return Be(u(this)?this.valueSeq():this)},toList:function(){return Ht(u(this)?this.valueSeq():this)},toString:function(){return"[Iterable]"},__toString:function(t,e){return 0===this.size?t+e:t+" "+this.toSeq().map(this.__toStringMapper).join(", ")+" "+e},concat:function(){var t=sn.call(arguments,0);return Oe(this,ve(this,t))},includes:function(t){return this.some((function(e){return W(e,t)}))},entries:function(){return this.__iterator(bn)},every:function(t,e){ft(this.size);var n=!0;return this.__iterate((function(r,i,o){if(!t.call(e,r,i,o))return n=!1,!1})),n},filter:function(t,e){return Oe(this,fe(this,t,e,!0))},find:function(t,e,n){var r=this.findEntry(t,e);return r?r[1]:n},forEach:function(t,e){return ft(this.size),this.__iterate(e?t.bind(e):t)},join:function(t){ft(this.size),t=void 0!==t?""+t:",";var e="",n=!0;return this.__iterate((function(r){n?n=!1:e+=t,e+=null!==r&&void 0!==r?r.toString():""})),e},keys:function(){return this.__iterator(Sn)},map:function(t,e){return Oe(this,se(this,t,e))},reduce:function(t,e,n){ft(this.size);var r,i;return arguments.length<2?i=!0:r=e,this.__iterate((function(e,o,u){i?(i=!1,r=e):r=t.call(n,r,e,o,u)})),r},reduceRight:function(t,e,n){var r=this.toKeyedSeq().reverse();return r.reduce.apply(r,arguments)},reverse:function(){return Oe(this,ce(this,!0))},slice:function(t,e){return Oe(this,pe(this,t,e,!0))},some:function(t,e){return!this.every($e(t),e)},sort:function(t){return Oe(this,Se(this,t))},values:function(){return this.__iterator(En)},butLast:function(){return this.slice(0,-1)},isEmpty:function(){return void 0!==this.size?0===this.size:!this.some((function(){return!0}))},count:function(t,e){return _(t?this.toSeq().filter(t,e):this)},countBy:function(t,e){return he(this,t,e)},equals:function(t){return X(this,t)},entrySeq:function(){var t=this;if(t._cache)return new L(t._cache);var e=t.toSeq().map(Ze).toIndexedSeq();return e.fromEntrySeq=function(){return t.toSeq()},e},filterNot:function(t,e){return this.filter($e(t),e)},findEntry:function(t,e,n){var r=n;return this.__iterate((function(n,i,o){if(t.call(e,n,i,o))return r=[i,n],!1})),r},findKey:function(t,e){var n=this.findEntry(t,e);return n&&n[0]},findLast:function(t,e,n){return this.toKeyedSeq().reverse().find(t,e,n)},findLastEntry:function(t,e,n){return this.toKeyedSeq().reverse().findEntry(t,e,n)},findLastKey:function(t,e){return this.toKeyedSeq().reverse().findKey(t,e)},first:function(){return this.find(v)},flatMap:function(t,e){return Oe(this,ge(this,t,e))},flatten:function(t){return Oe(this,ye(this,t,!0))},fromEntrySeq:function(){return new ue(this)},get:function(t,e){return this.find((function(e,n){return W(n,t)}),void 0,e)},getIn:function(t,e){for(var n,r=this,i=Re(t);!(n=i.next()).done;){var o=n.value;if(r=r&&r.get?r.get(o,yn):yn,r===yn)return e}return r},groupBy:function(t,e){return le(this,t,e)},has:function(t){return this.get(t,yn)!==yn},hasIn:function(t){return this.getIn(t,yn)!==yn},isSubset:function(t){return t="function"==typeof t.includes?t:e(t),this.every((function(e){return t.includes(e)}))},isSuperset:function(t){return t="function"==typeof t.isSubset?t:e(t),t.isSubset(this)},keyOf:function(t){return this.findKey((function(e){return W(e,t)}))},keySeq:function(){return this.toSeq().map(Qe).toIndexedSeq()},last:function(){return this.toSeq().reverse().first()},lastKeyOf:function(t){return this.toKeyedSeq().reverse().keyOf(t)},max:function(t){return Ee(this,t)},maxBy:function(t,e){return Ee(this,e,t)},min:function(t){return Ee(this,t?tn(t):rn)},minBy:function(t,e){return Ee(this,e?tn(e):rn,t)},rest:function(){return this.slice(1)},skip:function(t){return this.slice(Math.max(0,t))},skipLast:function(t){return Oe(this,this.toSeq().reverse().skip(t).reverse())},skipWhile:function(t,e){return Oe(this,de(this,t,e,!0))},skipUntil:function(t,e){return this.skipWhile($e(t),e)},sortBy:function(t,e){return Oe(this,Se(this,e,t))},take:function(t){return this.slice(0,Math.max(0,t))},takeLast:function(t){return Oe(this,this.toSeq().reverse().take(t).reverse())},takeWhile:function(t,e){return Oe(this,_e(this,t,e))},takeUntil:function(t,e){return this.takeWhile($e(t),e)},valueSeq:function(){return this.toIndexedSeq()},hashCode:function(){return this.__hash||(this.__hash=on(this))}});var ar=e.prototype;ar[cn]=!0,ar[wn]=ar.values,ar.__toJS=ar.toArray,ar.__toStringMapper=en,ar.inspect=ar.toSource=function(){return this.toString()},ar.chain=ar.flatMap,ar.contains=ar.includes,Xe(n,{flip:function(){return Oe(this,ae(this))},mapEntries:function(t,e){var n=this,r=0;return Oe(this,this.toSeq().map((function(i,o){return t.call(e,[o,i],r++,n)})).fromEntrySeq())},mapKeys:function(t,e){var n=this;return Oe(this,this.toSeq().flip().map((function(r,i){return t.call(e,r,i,n)})).flip())}});var sr=n.prototype;sr[fn]=!0,sr[wn]=ar.entries,sr.__toJS=ar.toObject,sr.__toStringMapper=function(t,e){return JSON.stringify(e)+": "+en(t)},Xe(r,{toKeyedSeq:function(){return new re(this,!1)},filter:function(t,e){return Oe(this,fe(this,t,e,!1))},findIndex:function(t,e){var n=this.findEntry(t,e);return n?n[0]:-1},indexOf:function(t){var e=this.keyOf(t);return void 0===e?-1:e},lastIndexOf:function(t){var e=this.lastKeyOf(t);return void 0===e?-1:e},reverse:function(){return Oe(this,ce(this,!1))},slice:function(t,e){return Oe(this,pe(this,t,e,!1))},splice:function(t,e){var n=arguments.length;if(e=Math.max(0|e,0),0===n||2===n&&!e)return this;t=g(t,t<0?this.count():this.size);var r=this.slice(0,t);return Oe(this,1===n?r:r.concat(p(arguments,2),this.slice(t+e)))},findLastIndex:function(t,e){var n=this.findLastEntry(t,e);return n?n[0]:-1},first:function(){return this.get(0)},flatten:function(t){return Oe(this,ye(this,t,!1))},get:function(t,e){return t=d(this,t),t<0||this.size===1/0||void 0!==this.size&&t>this.size?e:this.find((function(e,n){return n===t}),void 0,e)},has:function(t){return t=d(this,t),t>=0&&(void 0!==this.size?this.size===1/0||t-1&&t%1===0&&t<=Number.MAX_VALUE}var i=Function.prototype.bind;e.isString=function(t){return"string"==typeof t||"[object String]"===n(t)},e.isArray=Array.isArray||function(t){return"[object Array]"===n(t)},"function"!=typeof/./&&"object"!=typeof Int8Array?e.isFunction=function(t){return"function"==typeof t||!1}:e.isFunction=function(t){return"[object Function]"===toString.call(t)},e.isObject=function(t){var e=typeof t;return"function"===e||"object"===e&&!!t},e.extend=function(t){var e=arguments,n=arguments.length;if(!t||n<2)return t||{};for(var r=1;r0)){var e=this.reactorState.get("dirtyStores");if(0!==e.size){var n=c.default.Set().withMutations((function(n){n.union(t.observerState.get("any")),e.forEach((function(e){var r=t.observerState.getIn(["stores",e]);r&&n.union(r)}))}));n.forEach((function(e){var n=t.observerState.getIn(["observersMap",e]);if(n){var r=n.get("getter"),i=n.get("handler"),o=p.evaluate(t.prevReactorState,r),u=p.evaluate(t.reactorState,r);t.prevReactorState=o.reactorState,t.reactorState=u.reactorState;var a=o.result,s=u.result;c.default.is(a,s)||i.call(null,s)}}));var r=p.resetDirtyStores(this.reactorState);this.prevReactorState=r,this.reactorState=r}}}},{key:"batchStart",value:function(){this.__batchDepth++}},{key:"batchEnd",value:function(){if(this.__batchDepth--,this.__batchDepth<=0){this.__isDispatching=!0;try{this.__notify()}catch(t){throw this.__isDispatching=!1,t}this.__isDispatching=!1}}}]),t})();e.default=(0,m.toFactory)(E),t.exports=e.default},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e){var n={};return(0,o.each)(e,(function(e,r){n[r]=t.evaluate(e)})),n}Object.defineProperty(e,"__esModule",{value:!0});var o=n(4);e.default=function(t){return{getInitialState:function(){return i(t,this.getDataBindings())},componentDidMount:function(){var e=this;this.__unwatchFns=[],(0,o.each)(this.getDataBindings(),(function(n,i){var o=t.observe(n,(function(t){e.setState(r({},i,t))}));e.__unwatchFns.push(o)}))},componentWillUnmount:function(){for(var t=this;this.__unwatchFns.length;)t.__unwatchFns.shift()()}}},t.exports=e.default},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t,e){return new C({result:t,reactorState:e})}function o(t,e){return t.withMutations((function(t){(0,A.each)(e,(function(e,n){t.getIn(["stores",n])&&console.warn("Store already defined for id = "+n);var r=e.getInitialState();if(void 0===r&&f(t,"throwOnUndefinedStoreReturnValue"))throw new Error("Store getInitialState() must return a value, did you forget a return statement");if(f(t,"throwOnNonImmutableStore")&&!(0,O.isImmutableValue)(r))throw new Error("Store getInitialState() must return an immutable value, did you forget to call toImmutable");t.update("stores",(function(t){return t.set(n,e)})).update("state",(function(t){return t.set(n,r)})).update("dirtyStores",(function(t){return t.add(n)})).update("storeStates",(function(t){return S(t,[n])}))})),m(t)}))}function u(t,e){return t.withMutations((function(t){(0,A.each)(e,(function(e,n){t.update("stores",(function(t){return t.set(n,e)}))}))}))}function a(t,e,n){var r=t.get("logger");if(void 0===e&&f(t,"throwOnUndefinedActionType"))throw new Error("`dispatch` cannot be called with an `undefined` action type.");var i=t.get("state"),o=t.get("dirtyStores"),u=i.withMutations((function(u){r.dispatchStart(t,e,n),t.get("stores").forEach((function(i,a){var s=u.get(a),c=void 0;try{c=i.handle(s,e,n)}catch(e){throw r.dispatchError(t,e.message),e}if(void 0===c&&f(t,"throwOnUndefinedStoreReturnValue")){var h="Store handler must return a value, did you forget a return statement";throw r.dispatchError(t,h),new Error(h)}u.set(a,c),s!==c&&(o=o.add(a))})),r.dispatchEnd(t,u,o,i)})),a=t.set("state",u).set("dirtyStores",o).update("storeStates",(function(t){return S(t,o)}));return m(a)}function s(t,e){var n=[],r=(0,O.toImmutable)({}).withMutations((function(r){(0,A.each)(e,(function(e,i){var o=t.getIn(["stores",i]);if(o){var u=o.deserialize(e);void 0!==u&&(r.set(i,u),n.push(i))}}))})),i=b.default.Set(n);return t.update("state",(function(t){return t.merge(r)})).update("dirtyStores",(function(t){return t.union(i)})).update("storeStates",(function(t){return S(t,n)}))}function c(t,e,n){var r=e;(0,T.isKeyPath)(e)&&(e=(0,w.fromKeyPath)(e));var i=t.get("nextId"),o=(0,w.getStoreDeps)(e),u=b.default.Map({id:i,storeDeps:o,getterKey:r,getter:e,handler:n}),a=void 0;return a=0===o.size?t.update("any",(function(t){return t.add(i)})):t.withMutations((function(t){o.forEach((function(e){var n=["stores",e];t.hasIn(n)||t.setIn(n,b.default.Set()),t.updateIn(["stores",e],(function(t){return t.add(i)}))}))})),a=a.set("nextId",i+1).setIn(["observersMap",i],u),{observerState:a,entry:u}}function f(t,e){var n=t.getIn(["options",e]);if(void 0===n)throw new Error("Invalid option: "+e);return n}function h(t,e,n){var r=t.get("observersMap").filter((function(t){var r=t.get("getterKey"),i=!n||t.get("handler")===n;return!!i&&((0,T.isKeyPath)(e)&&(0,T.isKeyPath)(r)?(0,T.isEqual)(e,r):e===r)}));return t.withMutations((function(t){r.forEach((function(e){return l(t,e)}))}))}function l(t,e){return t.withMutations((function(t){var n=e.get("id"),r=e.get("storeDeps");0===r.size?t.update("any",(function(t){return t.remove(n)})):r.forEach((function(e){t.updateIn(["stores",e],(function(t){return t?t.remove(n):t}))})),t.removeIn(["observersMap",n])}))}function p(t){var e=t.get("state");return t.withMutations((function(t){var n=t.get("stores"),r=n.keySeq().toJS();n.forEach((function(n,r){var i=e.get(r),o=n.handleReset(i);if(void 0===o&&f(t,"throwOnUndefinedStoreReturnValue"))throw new Error("Store handleReset() must return a value, did you forget a return statement");if(f(t,"throwOnNonImmutableStore")&&!(0,O.isImmutableValue)(o))throw new Error("Store reset state must be an immutable value, did you forget to call toImmutable");t.setIn(["state",r],o)})),t.update("storeStates",(function(t){return S(t,r)})),v(t)}))}function _(t,e){var n=t.get("state");if((0,T.isKeyPath)(e))return i(n.getIn(e),t);if(!(0,w.isGetter)(e))throw new Error("evaluate must be passed a keyPath or Getter");var r=t.get("cache"),o=r.lookup(e),u=!o||y(t,o);return u&&(o=g(t,e)),i(o.get("value"),t.update("cache",(function(t){return u?t.miss(e,o):t.hit(e)})))}function d(t){var e={};return t.get("stores").forEach((function(n,r){var i=t.getIn(["state",r]),o=n.serialize(i);void 0!==o&&(e[r]=o)})),e}function v(t){return t.set("dirtyStores",b.default.Set())}function y(t,e){var n=e.get("storeStates");return!n.size||n.some((function(e,n){return t.getIn(["storeStates",n])!==e}))}function g(t,e){var n=(0,w.getDeps)(e).map((function(e){return _(t,e).result})),r=(0,w.getComputeFn)(e).apply(null,n),i=(0,w.getStoreDeps)(e),o=(0,O.toImmutable)({}).withMutations((function(e){i.forEach((function(n){var r=t.getIn(["storeStates",n]);e.set(n,r)}))}));return(0,I.CacheEntry)({value:r,storeStates:o,dispatchId:t.get("dispatchId")})}function m(t){return t.update("dispatchId",(function(t){return t+1}))}function S(t,e){return t.withMutations((function(t){e.forEach((function(e){var n=t.has(e)?t.get(e)+1:1;t.set(e,n)}))}))}Object.defineProperty(e,"__esModule",{value:!0}),e.registerStores=o,e.replaceStores=u,e.dispatch=a,e.loadState=s,e.addObserver=c,e.getOption=f,e.removeObserver=h,e.removeObserverByEntry=l,e.reset=p,e.evaluate=_,e.serialize=d,e.resetDirtyStores=v;var E=n(3),b=r(E),I=n(9),O=n(5),w=n(10),T=n(11),A=n(4),C=b.default.Record({result:null,reactorState:null})},function(t,e,n){function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(){return new s}Object.defineProperty(e,"__esModule",{value:!0});var o=(function(){function t(t,e){for(var n=0;nn.dispatchId)throw new Error("Refusing to cache older value");return n})))}},{key:"evict",value:function(e){return new t(this.cache.remove(e))}}]),t})();e.BasicCache=s;var c=1e3,f=1,h=(function(){function t(){var e=arguments.length<=0||void 0===arguments[0]?c:arguments[0],n=arguments.length<=1||void 0===arguments[1]?f:arguments[1],i=arguments.length<=2||void 0===arguments[2]?new s:arguments[2],o=arguments.length<=3||void 0===arguments[3]?(0,u.OrderedSet)():arguments[3];r(this,t),console.log("using LRU"),this.limit=e,this.evictCount=n,this.cache=i,this.lru=o}return o(t,[{key:"lookup",value:function(t,e){return this.cache.lookup(t,e)}},{key:"has",value:function(t){return this.cache.has(t)}},{key:"asMap",value:function(){return this.cache.asMap()}},{key:"hit",value:function(e){return this.cache.has(e)?new t(this.limit,this.evictCount,this.cache,this.lru.remove(e).add(e)):this}},{key:"miss",value:function(e,n){var r;if(this.lru.size>=this.limit){if(this.has(e))return new t(this.limit,this.evictCount,this.cache.miss(e,n),this.lru.remove(e).add(e));var i=this.lru.take(this.evictCount).reduce((function(t,e){return t.evict(e)}),this.cache).miss(e,n);r=new t(this.limit,this.evictCount,i,this.lru.skip(this.evictCount).add(e))}else r=new t(this.limit,this.evictCount,this.cache.miss(e,n),this.lru.add(e));return r}},{key:"evict",value:function(e){return this.cache.has(e)?new t(this.limit,this.evictCount,this.cache.evict(e),this.lru.remove(e)):this}}]),t})();e.LRUCache=h},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t){return(0,l.isArray)(t)&&(0,l.isFunction)(t[t.length-1])}function o(t){return t[t.length-1]}function u(t){return t.slice(0,t.length-1)}function a(t,e){e||(e=h.default.Set());var n=h.default.Set().withMutations((function(e){if(!i(t))throw new Error("getFlattenedDeps must be passed a Getter");u(t).forEach((function(t){if((0,p.isKeyPath)(t))e.add((0,f.List)(t));else{if(!i(t))throw new Error("Invalid getter, each dependency must be a KeyPath or Getter");e.union(a(t))}}))}));return e.union(n)}function s(t){if(!(0,p.isKeyPath)(t))throw new Error("Cannot create Getter from KeyPath: "+t);return[t,_]}function c(t){if(t.hasOwnProperty("__storeDeps"))return t.__storeDeps;var e=a(t).map((function(t){return t.first()})).filter((function(t){return!!t}));return Object.defineProperty(t,"__storeDeps",{enumerable:!1,configurable:!1,writable:!1,value:e}),e}Object.defineProperty(e,"__esModule",{value:!0});var f=n(3),h=r(f),l=n(4),p=n(11),_=function(t){return t};e.default={isGetter:i,getComputeFn:o,getFlattenedDeps:a,getStoreDeps:c,getDeps:u,fromKeyPath:s},t.exports=e.default},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t){return(0,s.isArray)(t)&&!(0,s.isFunction)(t[t.length-1])}function o(t,e){var n=a.default.List(t),r=a.default.List(e);return a.default.is(n,r)}Object.defineProperty(e,"__esModule",{value:!0}),e.isKeyPath=i,e.isEqual=o;var u=n(3),a=r(u),s=n(4)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var r=n(8),i={dispatchStart:function(t,e,n){(0,r.getOption)(t,"logDispatches")&&console.group&&(console.groupCollapsed("Dispatch: %s",e),console.group("payload"),console.debug(n),console.groupEnd())},dispatchError:function(t,e){(0,r.getOption)(t,"logDispatches")&&console.group&&(console.debug("Dispatch error: "+e),console.groupEnd())},dispatchEnd:function(t,e,n,i){(0,r.getOption)(t,"logDispatches")&&console.group&&((0,r.getOption)(t,"logDirtyStores")&&console.log("Stores updated:",n.toList().toJS()),(0,r.getOption)(t,"logAppState")&&console.debug("Dispatch done, new state: ",e.toJS()),console.groupEnd())}};e.ConsoleGroupLogger=i;var o={dispatchStart:function(t,e,n){},dispatchError:function(t,e){},dispatchEnd:function(t,e,n){}};e.NoopLogger=o},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),i=n(9),o=n(12),u=(0,r.Map)({logDispatches:!1,logAppState:!1,logDirtyStores:!1,throwOnUndefinedActionType:!1,throwOnUndefinedStoreReturnValue:!1,throwOnNonImmutableStore:!1,throwOnDispatchInDispatch:!1});e.PROD_OPTIONS=u;var a=(0,r.Map)({logDispatches:!0,logAppState:!0,logDirtyStores:!0,throwOnUndefinedActionType:!0,throwOnUndefinedStoreReturnValue:!0,throwOnNonImmutableStore:!0,throwOnDispatchInDispatch:!0});e.DEBUG_OPTIONS=a;var s=(0,r.Record)({dispatchId:0,state:(0,r.Map)(),stores:(0,r.Map)(),cache:(0,i.DefaultCache)(),logger:o.NoopLogger,storeStates:(0,r.Map)(),dirtyStores:(0,r.Set)(),debug:!1,options:u});e.ReactorState=s;var c=(0,r.Record)({any:(0,r.Set)(),stores:(0,r.Map)({}),observersMap:(0,r.Map)({}),nextId:1});e.ObserverState=c}])}))})),ke=t(je),Ne=function(t){var e,n={};if(!(t instanceof Object)||Array.isArray(t))throw new Error("keyMirror(...): Argument must be an object.");for(e in t)t.hasOwnProperty(e)&&(n[e]=e);return n},Pe=Ne,Ue=Pe({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),He=ke.Store,xe=ke.toImmutable,Ve=new He({getInitialState:function(){return xe({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Ue.VALIDATING_AUTH_TOKEN,n),this.on(Ue.VALID_AUTH_TOKEN,r),this.on(Ue.INVALID_AUTH_TOKEN,i)}}),qe=ke.Store,Fe=ke.toImmutable,Ge=new qe({getInitialState:function(){return Fe({authToken:null,host:""})},initialize:function(){this.on(Ue.VALID_AUTH_TOKEN,o),this.on(Ue.LOG_OUT,u)}}),Ke=ke.Store,Be=new Ke({getInitialState:function(){return!0},initialize:function(){this.on(Ue.VALID_AUTH_TOKEN,a)}}),Ye=Pe({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),Je=ke.Store,We=ke.toImmutable,Xe=new Je({getInitialState:function(){return We({isStreaming:!1,hasError:!1})},initialize:function(){this.on(Ye.STREAM_START,s),this.on(Ye.STREAM_ERROR,c),this.on(Ye.LOG_OUT,f)}}),Qe=1,Ze=2,$e=3,tn=function(t,e){this.url=t,this.options=e||{},this.commandId=1,this.commands={},this.connectionTries=0,this.eventListeners={},this.closeRequested=!1};tn.prototype.addEventListener=function(t,e){var n=this.eventListeners[t];n||(n=this.eventListeners[t]=[]),n.push(e)},tn.prototype.fireEvent=function(t){var e=this;(this.eventListeners[t]||[]).forEach((function(t){return t(e)}))},tn.prototype.connect=function(){var t=this;return new Promise(function(e,n){var r=t.commands;Object.keys(r).forEach((function(t){var e=r[t];e.reject&&e.reject(S($e,"Connection lost"))}));var i=!1;t.connectionTries+=1,t.socket=new WebSocket(t.url),t.socket.addEventListener("open",(function(){t.connectionTries=0})),t.socket.addEventListener("message",(function(o){var u=JSON.parse(o.data);switch(u.type){case"event":t.commands[u.id].eventCallback(u.event);break;case"result":u.success?t.commands[u.id].resolve(u):t.commands[u.id].reject(u.error), -delete t.commands[u.id];break;case"pong":break;case"auth_required":t.sendMessage(h(t.options.authToken));break;case"auth_invalid":n(Ze),i=!0;break;case"auth_ok":e(t),t.fireEvent("ready"),t.commandId=1,t.commands={},Object.keys(r).forEach((function(e){var n=r[e];n.eventType&&t.subscribeEvents(n.eventCallback,n.eventType).then((function(t){n.unsubscribe=t}))}))}})),t.socket.addEventListener("close",(function(){if(!i&&!t.closeRequested){0===t.connectionTries?t.fireEvent("disconnected"):n(Qe);var e=1e3*Math.min(t.connectionTries,5);setTimeout((function(){return t.connect()}),e)}}))})},tn.prototype.close=function(){this.closeRequested=!0,this.socket.close()},tn.prototype.getStates=function(){return this.sendMessagePromise(l()).then(E)},tn.prototype.getServices=function(){return this.sendMessagePromise(_()).then(E)},tn.prototype.getPanels=function(){return this.sendMessagePromise(d()).then(E)},tn.prototype.getConfig=function(){return this.sendMessagePromise(p()).then(E)},tn.prototype.callService=function(t,e,n){return this.sendMessagePromise(v(t,e,n))},tn.prototype.subscribeEvents=function(t,e){var n=this;return this.sendMessagePromise(y(e)).then((function(r){var i={eventCallback:t,eventType:e,unsubscribe:function(){return n.sendMessagePromise(g(r.id)).then((function(){delete n.commands[r.id]}))}};return n.commands[r.id]=i,function(){return i.unsubscribe()}}))},tn.prototype.ping=function(){return this.sendMessagePromise(m())},tn.prototype.sendMessage=function(t){this.socket.send(JSON.stringify(t))},tn.prototype.sendMessagePromise=function(t){var e=this;return new Promise(function(n,r){e.commandId+=1;var i=e.commandId;t.id=i,e.commands[i]={resolve:n,reject:r},e.sendMessage(t)})};var en=Pe({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),nn=ke.Store,rn=new nn({getInitialState:function(){return!0},initialize:function(){this.on(en.API_FETCH_ALL_START,(function(){return!0})),this.on(en.API_FETCH_ALL_SUCCESS,(function(){return!1})),this.on(en.API_FETCH_ALL_FAIL,(function(){return!1})),this.on(en.LOG_OUT,(function(){return!1}))}}),on=I,un=Pe({API_FETCH_SUCCESS:null,API_FETCH_START:null,API_FETCH_FAIL:null,API_SAVE_SUCCESS:null,API_SAVE_START:null,API_SAVE_FAIL:null,API_DELETE_SUCCESS:null,API_DELETE_START:null,API_DELETE_FAIL:null,LOG_OUT:null}),an=ke.Store,sn=ke.toImmutable,cn=new an({getInitialState:function(){return sn({})},initialize:function(){var t=this;this.on(un.API_FETCH_SUCCESS,O),this.on(un.API_SAVE_SUCCESS,O),this.on(un.API_DELETE_SUCCESS,w),this.on(un.LOG_OUT,(function(){return t.getInitialState()}))}}),fn=Object.prototype.hasOwnProperty,hn=Object.prototype.propertyIsEnumerable,ln=A()?Object.assign:function(t,e){for(var n,r,i=arguments,o=T(t),u=1;u199&&u.status<300?t(e):n(e)},u.onerror=function(){return n({})},r?(u.setRequestHeader("Content-Type","application/json;charset=UTF-8"),u.send(JSON.stringify(r))):u.send()})}function O(t,e){var n=e.model,r=e.result,i=e.params,o=n.entity;if(!r)return t;var u=i.replace?sn({}):t.get(o),a=Array.isArray(r)?r:[r],s=n.fromJSON||sn;return t.set(o,u.withMutations((function(t){for(var e=0;e6e4}function mt(t,e){var n=e.date;return n.toISOString()}function gt(){return Qr.getInitialState()}function St(t,e){var n=e.date,r=e.stateHistory;return 0===r.length?t.set(n,$r({})):t.withMutations((function(t){r.forEach((function(e){return t.setIn([n,e[0].entity_id],$r(e.map(In.fromJSON)))}))}))}function bt(){return ti.getInitialState()}function Et(t,e){var n=e.stateHistory;return t.withMutations((function(t){n.forEach((function(e){return t.set(e[0].entity_id,ii(e.map(In.fromJSON)))}))}))}function It(){return oi.getInitialState()}function Ot(t,e){var n=e.stateHistory,r=(new Date).getTime();return t.withMutations((function(t){n.forEach((function(e){return t.set(e[0].entity_id,r)})),history.length>1&&t.set(si,r)}))}function wt(){return ci.getInitialState()}function Tt(t,e){t.dispatch(Wr.ENTITY_HISTORY_DATE_SELECTED,{date:e})}function At(t,e){void 0===e&&(e=null),t.dispatch(Wr.RECENT_ENTITY_HISTORY_FETCH_START,{});var n="history/period";return null!==e&&(n+="?filter_entity_id="+e),on(t,"GET",n).then((function(e){return t.dispatch(Wr.RECENT_ENTITY_HISTORY_FETCH_SUCCESS,{stateHistory:e})}),(function(){return t.dispatch(Wr.RECENT_ENTITY_HISTORY_FETCH_ERROR,{})}))}function Dt(t,e){return t.dispatch(Wr.ENTITY_HISTORY_FETCH_START,{date:e}),on(t,"GET","history/period/"+e).then((function(n){return t.dispatch(Wr.ENTITY_HISTORY_FETCH_SUCCESS,{date:e,stateHistory:n})}),(function(){return t.dispatch(Wr.ENTITY_HISTORY_FETCH_ERROR,{})}))}function Ct(t){var e=t.evaluate(li);return Dt(t,e)}function zt(t){t.registerStores({currentEntityHistoryDate:Qr,entityHistory:ti,isLoadingEntityHistory:ni,recentEntityHistory:oi,recentEntityHistoryUpdated:ci})}function Rt(t){t.registerStores({moreInfoEntityId:Yr})}function Mt(t,e){var n=e.model,r=e.result,i=e.params;if(null===t||"entity"!==n.entity||!i.replace)return t;for(var o=0;o0?i=setTimeout(r,e-c):(i=null,n||(s=t.apply(u,o),i||(u=o=null)))}var i,o,u,a,s;null==e&&(e=100);var c=function(){u=this,o=arguments,a=(new Date).getTime();var c=n&&!i;return i||(i=setTimeout(r,e)),c&&(s=t.apply(u,o),u=o=null),s};return c.clear=function(){i&&(clearTimeout(i),i=null)},c}function Yt(t){var e=fo[t.hassId];e&&(e.scheduleHealthCheck.clear(),e.conn.close(),fo[t.hassId]=!1)}function Jt(t,e){void 0===e&&(e={});var n=e.syncOnInitialConnect;void 0===n&&(n=!0),Yt(t);var r=t.evaluate(Mo.authToken),i="https:"===document.location.protocol?"wss://":"ws://";i+=document.location.hostname,document.location.port&&(i+=":"+document.location.port),i+="/api/websocket",E(i,{authToken:r}).then((function(e){var r=Bt((function(){return e.ping()}),so);r(),e.socket.addEventListener("message",r),fo[t.hassId]={conn:e,scheduleHealthCheck:r},co.forEach((function(n){return e.subscribeEvents(ao.bind(null,t),n)})),t.batch((function(){t.dispatch(Ye.STREAM_START),n&&io.fetchAll(t)})),e.addEventListener("disconnected",(function(){t.dispatch(Ye.STREAM_ERROR)})),e.addEventListener("ready",(function(){t.batch((function(){t.dispatch(Ye.STREAM_START),io.fetchAll(t)}))}))}))}function Wt(t){t.registerStores({streamStatus:Xe})}function Xt(t,e,n){void 0===n&&(n={});var r=n.rememberAuth;void 0===r&&(r=!1);var i=n.host;void 0===i&&(i=""),t.dispatch(Ue.VALIDATING_AUTH_TOKEN,{authToken:e,host:i}),io.fetchAll(t).then((function(){t.dispatch(Ue.VALID_AUTH_TOKEN,{authToken:e,host:i,rememberAuth:r}),vo.start(t,{syncOnInitialConnect:!1})}),(function(e){void 0===e&&(e={});var n=e.message;void 0===n&&(n=go),t.dispatch(Ue.INVALID_AUTH_TOKEN,{errorMessage:n})}))}function Qt(t){t.dispatch(Ue.LOG_OUT,{})}function Zt(t){t.registerStores({authAttempt:Ve,authCurrent:Ge,rememberAuth:Be})}function $t(){if(!("localStorage"in window))return{};var t=window.localStorage,e="___test";try{return t.setItem(e,e),t.removeItem(e),t}catch(t){return{}}}function te(){var t=new Uo({debug:!1});return t.hassId=Ho++,t}function ee(t,e,n){Object.keys(n).forEach((function(r){var i=n[r];if("register"in i&&i.register(e),"getters"in i&&Object.defineProperty(t,r+"Getters",{value:i.getters,enumerable:!0}),"actions"in i){var o={};Object.getOwnPropertyNames(i.actions).forEach((function(t){"function"==typeof i.actions[t]&&Object.defineProperty(o,t,{value:i.actions[t].bind(null,e),enumerable:!0})})),Object.defineProperty(t,r+"Actions",{value:o,enumerable:!0})}}))}function ne(t,e){return xo(t.attributes.entity_id.map((function(t){return e.get(t)})).filter((function(t){return!!t})))}function re(t){return on(t,"GET","error_log")}function ie(t,e){var n=e.date;return n.toISOString()}function oe(){return Jo.getInitialState()}function ue(t,e){var n=e.date,r=e.entries;return t.set(n,eu(r.map($o.fromJSON)))}function ae(){return nu.getInitialState()}function se(t,e){var n=e.date;return t.set(n,(new Date).getTime())}function ce(){return ou.getInitialState()}function fe(t,e){t.dispatch(Bo.LOGBOOK_DATE_SELECTED,{date:e})}function he(t,e){t.dispatch(Bo.LOGBOOK_ENTRIES_FETCH_START,{date:e}),on(t,"GET","logbook/"+e).then((function(n){return t.dispatch(Bo.LOGBOOK_ENTRIES_FETCH_SUCCESS,{date:e,entries:n})}),(function(){return t.dispatch(Bo.LOGBOOK_ENTRIES_FETCH_ERROR,{})}))}function le(t){return!t||(new Date).getTime()-t>su}function pe(t){t.registerStores({currentLogbookDate:Jo,isLoadingLogbookEntries:Xo,logbookEntries:nu,logbookEntriesUpdated:ou})}function _e(t){return t.set("active",!0)}function de(t){return t.set("active",!1)}function ve(){return Su.getInitialState()}function ye(t){return navigator.serviceWorker.getRegistration().then((function(t){if(!t)throw new Error("No service worker registered.");return t.pushManager.subscribe({userVisibleOnly:!0})})).then((function(e){var n;return n=navigator.userAgent.toLowerCase().indexOf("firefox")>-1?"firefox":"chrome",on(t,"POST","notify.html5",{subscription:e,browser:n}).then((function(){return t.dispatch(yu.PUSH_NOTIFICATIONS_SUBSCRIBE,{})})).then((function(){return!0}))})).catch((function(e){var n;return n=e.message&&e.message.indexOf("gcm_sender_id")!==-1?"Please setup the notify.html5 platform.":"Notification registration failed.",console.error(e),Vn.createNotification(t,n),!1}))}function me(t){return navigator.serviceWorker.getRegistration().then((function(t){if(!t)throw new Error("No service worker registered");return t.pushManager.subscribe({userVisibleOnly:!0})})).then((function(e){return on(t,"DELETE","notify.html5",{subscription:e}).then((function(){return e.unsubscribe()})).then((function(){return t.dispatch(yu.PUSH_NOTIFICATIONS_UNSUBSCRIBE,{})})).then((function(){return!0}))})).catch((function(e){var n="Failed unsubscribing for push notifications.";return console.error(e),Vn.createNotification(t,n),!1}))}function ge(t){t.registerStores({pushNotifications:Su})}function Se(t,e){return on(t,"POST","template",{template:e})}function be(t){return t.set("isListening",!0)}function Ee(t,e){var n=e.interimTranscript,r=e.finalTranscript;return t.withMutations((function(t){return t.set("isListening",!0).set("isTransmitting",!1).set("interimTranscript",n).set("finalTranscript",r)}))}function Ie(t,e){var n=e.finalTranscript;return t.withMutations((function(t){return t.set("isListening",!1).set("isTransmitting",!0).set("interimTranscript","").set("finalTranscript",n)}))}function Oe(){return ku.getInitialState()}function we(){return ku.getInitialState()}function Te(){return ku.getInitialState()}function Ae(t){return Pu[t.hassId]}function De(t){var e=Ae(t);if(e){var n=e.finalTranscript||e.interimTranscript;t.dispatch(Lu.VOICE_TRANSMITTING,{finalTranscript:n}),tr.callService(t,"conversation","process",{text:n}).then((function(){t.dispatch(Lu.VOICE_DONE)}),(function(){t.dispatch(Lu.VOICE_ERROR)}))}}function Ce(t){var e=Ae(t);e&&(e.recognition.stop(),Pu[t.hassId]=!1)}function ze(t){De(t),Ce(t)}function Re(t){var e=ze.bind(null,t);e();var n=new webkitSpeechRecognition;Pu[t.hassId]={recognition:n,interimTranscript:"",finalTranscript:""},n.interimResults=!0,n.onstart=function(){return t.dispatch(Lu.VOICE_START)},n.onerror=function(){return t.dispatch(Lu.VOICE_ERROR)},n.onend=e,n.onresult=function(e){var n=Ae(t);if(n){for(var r="",i="",o=e.resultIndex;o=n)}function c(t,e){return h(t,e,0)}function f(t,e){return h(t,e,e)}function h(t,e,n){return void 0===t?n:t<0?Math.max(0,e+t):void 0===e?t:Math.min(e,t)}function l(t){return v(t)?t:C(t)}function p(t){return y(t)?t:z(t)}function _(t){return m(t)?t:R(t)}function d(t){return v(t)&&!g(t)?t:M(t)}function v(t){return!(!t||!t[dn])}function y(t){return!(!t||!t[vn])}function m(t){return!(!t||!t[yn])}function g(t){return y(t)||m(t)}function S(t){return!(!t||!t[mn])}function b(t){this.next=t}function E(t,e,n,r){var i=0===t?e:1===t?n:[e,n];return r?r.value=i:r={value:i,done:!1},r}function I(){return{value:void 0,done:!0}}function O(t){return!!A(t)}function w(t){return t&&"function"==typeof t.next}function T(t){var e=A(t);return e&&e.call(t)}function A(t){var e=t&&(En&&t[En]||t[In]);if("function"==typeof e)return e}function D(t){return t&&"number"==typeof t.length}function C(t){return null===t||void 0===t?U():v(t)?t.toSeq():V(t)}function z(t){return null===t||void 0===t?U().toKeyedSeq():v(t)?y(t)?t.toSeq():t.fromEntrySeq():H(t)}function R(t){return null===t||void 0===t?U():v(t)?y(t)?t.entrySeq():t.toIndexedSeq():x(t)}function M(t){return(null===t||void 0===t?U():v(t)?y(t)?t.entrySeq():t:x(t)).toSetSeq()}function L(t){this._array=t,this.size=t.length}function j(t){var e=Object.keys(t);this._object=t,this._keys=e,this.size=e.length}function N(t){this._iterable=t,this.size=t.length||t.size}function k(t){this._iterator=t,this._iteratorCache=[]}function P(t){return!(!t||!t[wn])}function U(){return Tn||(Tn=new L([]))}function H(t){var e=Array.isArray(t)?new L(t).fromEntrySeq():w(t)?new k(t).fromEntrySeq():O(t)?new N(t).fromEntrySeq():"object"==typeof t?new j(t):void 0;if(!e)throw new TypeError("Expected Array or iterable object of [k, v] entries, or keyed object: "+t);return e}function x(t){var e=q(t);if(!e)throw new TypeError("Expected Array or iterable object of values: "+t);return e}function V(t){var e=q(t)||"object"==typeof t&&new j(t);if(!e)throw new TypeError("Expected Array or iterable object of values, or keyed object: "+t);return e}function q(t){return D(t)?new L(t):w(t)?new k(t):O(t)?new N(t):void 0}function F(t,e,n,r){var i=t._cache;if(i){for(var o=i.length-1,u=0;u<=o;u++){var a=i[n?o-u:u];if(e(a[1],r?a[0]:u,t)===!1)return u+1}return u}return t.__iterateUncached(e,n)}function G(t,e,n,r){var i=t._cache;if(i){var o=i.length-1,u=0;return new b(function(){var t=i[n?o-u:u];return u++>o?I():E(e,r?t[0]:u-1,t[1])})}return t.__iteratorUncached(e,n)}function K(){throw TypeError("Abstract")}function B(){}function Y(){}function J(){}function W(t,e){if(t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1;if("function"==typeof t.valueOf&&"function"==typeof e.valueOf){if(t=t.valueOf(),e=e.valueOf(),t===e||t!==t&&e!==e)return!0;if(!t||!e)return!1}return!("function"!=typeof t.equals||"function"!=typeof e.equals||!t.equals(e))}function X(t,e){return e?Q(e,t,"",{"":t}):Z(t)}function Q(t,e,n,r){return Array.isArray(e)?t.call(r,n,R(e).map((function(n,r){return Q(t,n,r,e)}))):$(e)?t.call(r,n,z(e).map((function(n,r){return Q(t,n,r,e)}))):e}function Z(t){return Array.isArray(t)?R(t).map(Z).toList():$(t)?z(t).map(Z).toMap():t}function $(t){return t&&(t.constructor===Object||void 0===t.constructor)}function tt(t){return t>>>1&1073741824|3221225471&t}function et(t){if(t===!1||null===t||void 0===t)return 0;if("function"==typeof t.valueOf&&(t=t.valueOf(),t===!1||null===t||void 0===t))return 0;if(t===!0)return 1;var e=typeof t;if("number"===e){var n=0|t;for(n!==t&&(n^=4294967295*t);t>4294967295;)t/=4294967295,n^=t;return tt(n)}return"string"===e?t.length>jn?nt(t):rt(t):"function"==typeof t.hashCode?t.hashCode():it(t)}function nt(t){var e=Pn[t];return void 0===e&&(e=rt(t),kn===Nn&&(kn=0,Pn={}),kn++,Pn[t]=e),e}function rt(t){for(var e=0,n=0;n0)switch(t.nodeType){case 1:return t.uniqueID;case 9:return t.documentElement&&t.documentElement.uniqueID}}function ut(t,e){if(!t)throw new Error(e)}function at(t){ut(t!==1/0,"Cannot perform this action with an infinite size.")}function st(t,e){this._iter=t,this._useKeys=e,this.size=t.size}function ct(t){this._iter=t,this.size=t.size}function ft(t){this._iter=t,this.size=t.size}function ht(t){this._iter=t,this.size=t.size}function lt(t){var e=Lt(t);return e._iter=t,e.size=t.size,e.flip=function(){return t},e.reverse=function(){var e=t.reverse.apply(this);return e.flip=function(){return t.reverse()},e},e.has=function(e){return t.includes(e)},e.includes=function(e){return t.has(e)},e.cacheResult=jt,e.__iterateUncached=function(e,n){var r=this;return t.__iterate((function(t,n){return e(n,t,r)!==!1}),n)},e.__iteratorUncached=function(e,n){if(e===bn){var r=t.__iterator(e,n);return new b(function(){var t=r.next();if(!t.done){var e=t.value[0];t.value[0]=t.value[1],t.value[1]=e}return t})}return t.__iterator(e===Sn?gn:Sn,n)},e}function pt(t,e,n){var r=Lt(t);return r.size=t.size,r.has=function(e){return t.has(e)},r.get=function(r,i){var o=t.get(r,ln);return o===ln?i:e.call(n,o,r,t)},r.__iterateUncached=function(r,i){var o=this;return t.__iterate((function(t,i,u){return r(e.call(n,t,i,u),i,o)!==!1}),i)},r.__iteratorUncached=function(r,i){var o=t.__iterator(bn,i);return new b(function(){var i=o.next();if(i.done)return i;var u=i.value,a=u[0];return E(r,a,e.call(n,u[1],a,t),i)})},r}function _t(t,e){var n=Lt(t);return n._iter=t,n.size=t.size,n.reverse=function(){return t},t.flip&&(n.flip=function(){var e=lt(t);return e.reverse=function(){return t.flip()},e}),n.get=function(n,r){return t.get(e?n:-1-n,r)},n.has=function(n){return t.has(e?n:-1-n)},n.includes=function(e){return t.includes(e)},n.cacheResult=jt,n.__iterate=function(e,n){var r=this;return t.__iterate((function(t,n){return e(t,n,r)}),!n)},n.__iterator=function(e,n){return t.__iterator(e,!n)},n}function dt(t,e,n,r){var i=Lt(t);return r&&(i.has=function(r){var i=t.get(r,ln);return i!==ln&&!!e.call(n,i,r,t)},i.get=function(r,i){var o=t.get(r,ln);return o!==ln&&e.call(n,o,r,t)?o:i}),i.__iterateUncached=function(i,o){var u=this,a=0;return t.__iterate((function(t,o,s){if(e.call(n,t,o,s))return a++,i(t,r?o:a-1,u)}),o),a},i.__iteratorUncached=function(i,o){var u=t.__iterator(bn,o),a=0;return new b(function(){for(;;){var o=u.next();if(o.done)return o;var s=o.value,c=s[0],f=s[1];if(e.call(n,f,c,t))return E(i,r?c:a++,f,o)}})},i}function vt(t,e,n){var r=Pt().asMutable();return t.__iterate((function(i,o){r.update(e.call(n,i,o,t),0,(function(t){return t+1}))})),r.asImmutable()}function yt(t,e,n){var r=y(t),i=(S(t)?Ie():Pt()).asMutable();t.__iterate((function(o,u){i.update(e.call(n,o,u,t),(function(t){return t=t||[],t.push(r?[u,o]:o),t}))}));var o=Mt(t);return i.map((function(e){return Ct(t,o(e))}))}function mt(t,e,n,r){var i=t.size;if(void 0!==e&&(e|=0),void 0!==n&&(n|=0),s(e,n,i))return t;var o=c(e,i),a=f(n,i);if(o!==o||a!==a)return mt(t.toSeq().cacheResult(),e,n,r);var h,l=a-o;l===l&&(h=l<0?0:l);var p=Lt(t);return p.size=0===h?h:t.size&&h||void 0,!r&&P(t)&&h>=0&&(p.get=function(e,n){return e=u(this,e),e>=0&&eh)return I();var t=i.next();return r||e===Sn?t:e===gn?E(e,a-1,void 0,t):E(e,a-1,t.value[1],t)})},p}function gt(t,e,n){var r=Lt(t);return r.__iterateUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterate(r,i);var u=0;return t.__iterate((function(t,i,a){return e.call(n,t,i,a)&&++u&&r(t,i,o)})),u},r.__iteratorUncached=function(r,i){var o=this;if(i)return this.cacheResult().__iterator(r,i);var u=t.__iterator(bn,i),a=!0;return new b(function(){if(!a)return I();var t=u.next();if(t.done)return t;var i=t.value,s=i[0],c=i[1];return e.call(n,c,s,o)?r===bn?t:E(r,s,c,t):(a=!1,I())})},r}function St(t,e,n,r){var i=Lt(t);return i.__iterateUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterate(i,o);var a=!0,s=0;return t.__iterate((function(t,o,c){if(!a||!(a=e.call(n,t,o,c)))return s++,i(t,r?o:s-1,u)})),s},i.__iteratorUncached=function(i,o){var u=this;if(o)return this.cacheResult().__iterator(i,o);var a=t.__iterator(bn,o),s=!0,c=0;return new b(function(){var t,o,f;do{if(t=a.next(),t.done)return r||i===Sn?t:i===gn?E(i,c++,void 0,t):E(i,c++,t.value[1],t);var h=t.value;o=h[0],f=h[1],s&&(s=e.call(n,f,o,u))}while(s);return i===bn?t:E(i,o,f,t)})},i}function bt(t,e){var n=y(t),r=[t].concat(e).map((function(t){return v(t)?n&&(t=p(t)):t=n?H(t):x(Array.isArray(t)?t:[t]),t})).filter((function(t){return 0!==t.size}));if(0===r.length)return t;if(1===r.length){var i=r[0];if(i===t||n&&y(i)||m(t)&&m(i))return i}var o=new L(r);return n?o=o.toKeyedSeq():m(t)||(o=o.toSetSeq()),o=o.flatten(!0),o.size=r.reduce((function(t,e){if(void 0!==t){var n=e.size;if(void 0!==n)return t+n}}),0),o}function Et(t,e,n){var r=Lt(t);return r.__iterateUncached=function(r,i){function o(t,s){var c=this;t.__iterate((function(t,i){return(!e||s0}function Dt(t,e,n){var r=Lt(t);return r.size=new L(n).map((function(t){return t.size})).min(),r.__iterate=function(t,e){for(var n,r=this,i=this.__iterator(Sn,e),o=0;!(n=i.next()).done&&t(n.value,o++,r)!==!1;);return o},r.__iteratorUncached=function(t,r){var i=n.map((function(t){return t=l(t),T(r?t.reverse():t)})),o=0,u=!1; +return new b(function(){var n;return u||(n=i.map((function(t){return t.next()})),u=n.some((function(t){return t.done}))),u?I():E(t,o++,e.apply(null,n.map((function(t){return t.value}))))})},r}function Ct(t,e){return P(t)?e:t.constructor(e)}function zt(t){if(t!==Object(t))throw new TypeError("Expected [K, V] tuple: "+t)}function Rt(t){return at(t.size),o(t)}function Mt(t){return y(t)?p:m(t)?_:d}function Lt(t){return Object.create((y(t)?z:m(t)?R:M).prototype)}function jt(){return this._iter.cacheResult?(this._iter.cacheResult(),this.size=this._iter.size,this):C.prototype.cacheResult.call(this)}function Nt(t,e){return t>e?1:t>>n)&hn,a=(0===n?r:r>>>n)&hn,s=u===a?[Zt(t,e,n+cn,r,i)]:(o=new Ft(e,r,i),u>>=1)u[a]=1&n?e[o++]:void 0;return u[r]=i,new Vt(t,o+1,u)}function ne(t,e,n){for(var r=[],i=0;i>1&1431655765,t=(858993459&t)+(t>>2&858993459),t=t+(t>>4)&252645135,t+=t>>8,t+=t>>16,127&t}function ae(t,e,n,r){var o=r?t:i(t);return o[e]=n,o}function se(t,e,n,r){var i=t.length+1;if(r&&e+1===i)return t[e]=n,t;for(var o=new Array(i),u=0,a=0;a0&&ro?0:o-n,c=u-n;return c>fn&&(c=fn),function(){if(i===c)return Yn;var t=e?--c:i++;return r&&r[t]}}function i(t,r,i){var a,s=t&&t.array,c=i>o?0:o-i>>r,f=(u-i>>r)+1;return f>fn&&(f=fn),function(){for(;;){if(a){var t=a();if(t!==Yn)return t;a=null}if(c===f)return Yn;var o=e?--f:c++;a=n(s&&s[o],r-cn,i+(o<=t.size||n<0)return t.withMutations((function(t){n<0?Se(t,n).set(0,r):Se(t,0,n+1).set(n,r)}));n+=t._origin;var i=t._tail,o=t._root,a=e(_n);return n>=Ee(t._capacity)?i=ye(i,t.__ownerID,0,n,r,a):o=ye(o,t.__ownerID,t._level,n,r,a),a.value?t.__ownerID?(t._root=o,t._tail=i,t.__hash=void 0,t.__altered=!0,t):_e(t._origin,t._capacity,t._level,o,i):t}function ye(t,e,r,i,o,u){var a=i>>>r&hn,s=t&&a0){var f=t&&t.array[a],h=ye(f,e,r-cn,i,o,u);return h===f?t:(c=me(t,e),c.array[a]=h,c)}return s&&t.array[a]===o?t:(n(u),c=me(t,e),void 0===o&&a===c.array.length-1?c.array.pop():c.array[a]=o,c)}function me(t,e){return e&&t&&e===t.ownerID?t:new le(t?t.array.slice():[],e)}function ge(t,e){if(e>=Ee(t._capacity))return t._tail;if(e<1<0;)n=n.array[e>>>r&hn],r-=cn;return n}}function Se(t,e,n){void 0!==e&&(e|=0),void 0!==n&&(n|=0);var i=t.__ownerID||new r,o=t._origin,u=t._capacity,a=o+e,s=void 0===n?u:n<0?u+n:o+n;if(a===o&&s===u)return t;if(a>=s)return t.clear();for(var c=t._level,f=t._root,h=0;a+h<0;)f=new le(f&&f.array.length?[void 0,f]:[],i),c+=cn,h+=1<=1<l?new le([],i):_;if(_&&p>l&&acn;y-=cn){var m=l>>>y&hn;v=v.array[m]=me(v.array[m],i)}v.array[l>>>cn&hn]=_}if(s=p)a-=p,s-=p,c=cn,f=null,d=d&&d.removeBefore(i,0,a);else if(a>o||p>>c&hn;if(g!==p>>>c&hn)break;g&&(h+=(1<o&&(f=f.removeBefore(i,c,a-h)),f&&pi&&(i=a.size),v(u)||(a=a.map((function(t){return X(t)}))),r.push(a)}return i>t.size&&(t=t.setSize(i)),ie(t,e,r)}function Ee(t){return t>>cn<=fn&&u.size>=2*o.size?(i=u.filter((function(t,e){return void 0!==t&&a!==e})),r=i.toKeyedSeq().map((function(t){return t[0]})).flip().toMap(),t.__ownerID&&(r.__ownerID=i.__ownerID=t.__ownerID)):(r=o.remove(e),i=a===u.size-1?u.pop():u.set(a,void 0))}else if(s){if(n===u.get(a)[1])return t;r=o,i=u.set(a,[e,n])}else r=o.set(e,u.size),i=u.set(u.size,[e,n]);return t.__ownerID?(t.size=r.size,t._map=r,t._list=i,t.__hash=void 0,t):we(r,i)}function De(t){return null===t||void 0===t?Re():Ce(t)?t:Re().unshiftAll(t)}function Ce(t){return!(!t||!t[Wn])}function ze(t,e,n,r){var i=Object.create(Xn);return i.size=t,i._head=e,i.__ownerID=n,i.__hash=r,i.__altered=!1,i}function Re(){return Qn||(Qn=ze(0))}function Me(t){return null===t||void 0===t?ke():Le(t)&&!S(t)?t:ke().withMutations((function(e){var n=d(t);at(n.size),n.forEach((function(t){return e.add(t)}))}))}function Le(t){return!(!t||!t[Zn])}function je(t,e){return t.__ownerID?(t.size=e.size,t._map=e,t):e===t._map?t:0===e.size?t.__empty():t.__make(e)}function Ne(t,e){var n=Object.create($n);return n.size=t?t.size:0,n._map=t,n.__ownerID=e,n}function ke(){return tr||(tr=Ne(Jt()))}function Pe(t){return null===t||void 0===t?xe():Ue(t)?t:xe().withMutations((function(e){var n=d(t);at(n.size),n.forEach((function(t){return e.add(t)}))}))}function Ue(t){return Le(t)&&S(t)}function He(t,e){var n=Object.create(er);return n.size=t?t.size:0,n._map=t,n.__ownerID=e,n}function xe(){return nr||(nr=He(Te()))}function Ve(t,e){var n,r=function(o){if(o instanceof r)return o;if(!(this instanceof r))return new r(o);if(!n){n=!0;var u=Object.keys(t);Ge(i,u),i.size=u.length,i._name=e,i._keys=u,i._defaultValues=t}this._map=Pt(o)},i=r.prototype=Object.create(rr);return i.constructor=r,r}function qe(t,e,n){var r=Object.create(Object.getPrototypeOf(t));return r._map=e,r.__ownerID=n,r}function Fe(t){return t._name||t.constructor.name||"Record"}function Ge(t,e){try{e.forEach(Ke.bind(void 0,t))}catch(t){}}function Ke(t,e){Object.defineProperty(t,e,{get:function(){return this.get(e)},set:function(t){ut(this.__ownerID,"Cannot set on an immutable record."),this.set(e,t)}})}function Be(t,e){if(t===e)return!0;if(!v(e)||void 0!==t.size&&void 0!==e.size&&t.size!==e.size||void 0!==t.__hash&&void 0!==e.__hash&&t.__hash!==e.__hash||y(t)!==y(e)||m(t)!==m(e)||S(t)!==S(e))return!1;if(0===t.size&&0===e.size)return!0;var n=!g(t);if(S(t)){var r=t.entries();return e.every((function(t,e){var i=r.next().value;return i&&W(i[1],t)&&(n||W(i[0],e))}))&&r.next().done}var i=!1;if(void 0===t.size)if(void 0===e.size)"function"==typeof t.cacheResult&&t.cacheResult();else{i=!0;var o=t;t=e,e=o}var u=!0,a=e.__iterate((function(e,r){if(n?!t.has(e):i?!W(e,t.get(r,ln)):!W(t.get(r,ln),e))return u=!1,!1}));return u&&t.size===a}function Ye(t,e,n){if(!(this instanceof Ye))return new Ye(t,e,n);if(ut(0!==n,"Cannot step a Range by 0"),t=t||0,void 0===e&&(e=1/0),n=void 0===n?1:Math.abs(n),ee?-1:0}function rn(t){if(t.size===1/0)return 0;var e=S(t),n=y(t),r=e?1:0,i=t.__iterate(n?e?function(t,e){r=31*r+un(et(t),et(e))|0}:function(t,e){r=r+un(et(t),et(e))|0}:e?function(t){r=31*r+et(t)|0}:function(t){r=r+et(t)|0});return on(i,r)}function on(t,e){return e=Dn(e,3432918353),e=Dn(e<<15|e>>>-15,461845907),e=Dn(e<<13|e>>>-13,5),e=(e+3864292196|0)^t,e=Dn(e^e>>>16,2246822507),e=Dn(e^e>>>13,3266489909),e=tt(e^e>>>16)}function un(t,e){return t^e+2654435769+(t<<6)+(t>>2)|0}var an=Array.prototype.slice,sn="delete",cn=5,fn=1<r?I():E(t,i,n[e?r-i++:i++])})},t(j,z),j.prototype.get=function(t,e){return void 0===e||this.has(t)?this._object[t]:e},j.prototype.has=function(t){return this._object.hasOwnProperty(t)},j.prototype.__iterate=function(t,e){for(var n=this,r=this._object,i=this._keys,o=i.length-1,u=0;u<=o;u++){var a=i[e?o-u:u];if(t(r[a],a,n)===!1)return u+1}return u},j.prototype.__iterator=function(t,e){var n=this._object,r=this._keys,i=r.length-1,o=0;return new b(function(){var u=r[e?i-o:o];return o++>i?I():E(t,u,n[u])})},j.prototype[mn]=!0,t(N,R),N.prototype.__iterateUncached=function(t,e){var n=this;if(e)return this.cacheResult().__iterate(t,e);var r=this._iterable,i=T(r),o=0;if(w(i))for(var u;!(u=i.next()).done&&t(u.value,o++,n)!==!1;);return o},N.prototype.__iteratorUncached=function(t,e){if(e)return this.cacheResult().__iterator(t,e);var n=this._iterable,r=T(n);if(!w(r))return new b(I);var i=0;return new b(function(){var e=r.next();return e.done?e:E(t,i++,e.value)})},t(k,R),k.prototype.__iterateUncached=function(t,e){var n=this;if(e)return this.cacheResult().__iterate(t,e);for(var r=this._iterator,i=this._iteratorCache,o=0;o=r.length){var e=n.next();if(e.done)return e;r[i]=e.value}return E(t,i,r[i++])})};var Tn;t(K,l),t(B,K),t(Y,K),t(J,K),K.Keyed=B,K.Indexed=Y,K.Set=J;var An,Dn="function"==typeof Math.imul&&Math.imul(4294967295,2)===-2?Math.imul:function(t,e){t|=0,e|=0;var n=65535&t,r=65535&e;return n*r+((t>>>16)*r+n*(e>>>16)<<16>>>0)|0},Cn=Object.isExtensible,zn=(function(){try{return Object.defineProperty({},"@",{}),!0}catch(t){return!1}})(),Rn="function"==typeof WeakMap;Rn&&(An=new WeakMap);var Mn=0,Ln="__immutablehash__";"function"==typeof Symbol&&(Ln=Symbol(Ln));var jn=16,Nn=255,kn=0,Pn={};t(st,z),st.prototype.get=function(t,e){return this._iter.get(t,e)},st.prototype.has=function(t){return this._iter.has(t)},st.prototype.valueSeq=function(){return this._iter.valueSeq()},st.prototype.reverse=function(){var t=this,e=_t(this,!0);return this._useKeys||(e.valueSeq=function(){return t._iter.toSeq().reverse()}),e},st.prototype.map=function(t,e){var n=this,r=pt(this,t,e);return this._useKeys||(r.valueSeq=function(){return n._iter.toSeq().map(t,e)}),r},st.prototype.__iterate=function(t,e){var n,r=this;return this._iter.__iterate(this._useKeys?function(e,n){return t(e,n,r)}:(n=e?Rt(this):0,function(i){return t(i,e?--n:n++,r)}),e)},st.prototype.__iterator=function(t,e){if(this._useKeys)return this._iter.__iterator(t,e);var n=this._iter.__iterator(Sn,e),r=e?Rt(this):0;return new b(function(){var i=n.next();return i.done?i:E(t,e?--r:r++,i.value,i)})},st.prototype[mn]=!0,t(ct,R),ct.prototype.includes=function(t){return this._iter.includes(t)},ct.prototype.__iterate=function(t,e){var n=this,r=0;return this._iter.__iterate((function(e){return t(e,r++,n)}),e)},ct.prototype.__iterator=function(t,e){var n=this._iter.__iterator(Sn,e),r=0;return new b(function(){var e=n.next();return e.done?e:E(t,r++,e.value,e)})},t(ft,M),ft.prototype.has=function(t){return this._iter.includes(t)},ft.prototype.__iterate=function(t,e){var n=this;return this._iter.__iterate((function(e){return t(e,e,n)}),e)},ft.prototype.__iterator=function(t,e){var n=this._iter.__iterator(Sn,e);return new b(function(){var e=n.next();return e.done?e:E(t,e.value,e.value,e)})},t(ht,z),ht.prototype.entrySeq=function(){return this._iter.toSeq()},ht.prototype.__iterate=function(t,e){var n=this;return this._iter.__iterate((function(e){if(e){zt(e);var r=v(e);return t(r?e.get(1):e[1],r?e.get(0):e[0],n)}}),e)},ht.prototype.__iterator=function(t,e){var n=this._iter.__iterator(Sn,e);return new b(function(){for(;;){var e=n.next();if(e.done)return e;var r=e.value;if(r){zt(r);var i=v(r);return E(t,i?r.get(0):r[0],i?r.get(1):r[1],e)}}})},ct.prototype.cacheResult=st.prototype.cacheResult=ft.prototype.cacheResult=ht.prototype.cacheResult=jt,t(Pt,B),Pt.prototype.toString=function(){return this.__toString("Map {","}")},Pt.prototype.get=function(t,e){return this._root?this._root.get(0,void 0,t,e):e},Pt.prototype.set=function(t,e){return Wt(this,t,e)},Pt.prototype.setIn=function(t,e){return this.updateIn(t,ln,(function(){return e}))},Pt.prototype.remove=function(t){return Wt(this,t,ln)},Pt.prototype.deleteIn=function(t){return this.updateIn(t,(function(){return ln}))},Pt.prototype.update=function(t,e,n){return 1===arguments.length?t(this):this.updateIn([t],e,n)},Pt.prototype.updateIn=function(t,e,n){n||(n=e,e=void 0);var r=oe(this,kt(t),e,n);return r===ln?void 0:r},Pt.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._root=null,this.__hash=void 0,this.__altered=!0,this):Jt()},Pt.prototype.merge=function(){return ne(this,void 0,arguments)},Pt.prototype.mergeWith=function(t){var e=an.call(arguments,1);return ne(this,t,e)},Pt.prototype.mergeIn=function(t){var e=an.call(arguments,1);return this.updateIn(t,Jt(),(function(t){return"function"==typeof t.merge?t.merge.apply(t,e):e[e.length-1]}))},Pt.prototype.mergeDeep=function(){return ne(this,re(void 0),arguments)},Pt.prototype.mergeDeepWith=function(t){var e=an.call(arguments,1);return ne(this,re(t),e)},Pt.prototype.mergeDeepIn=function(t){var e=an.call(arguments,1);return this.updateIn(t,Jt(),(function(t){return"function"==typeof t.mergeDeep?t.mergeDeep.apply(t,e):e[e.length-1]}))},Pt.prototype.sort=function(t){return Ie(wt(this,t))},Pt.prototype.sortBy=function(t,e){return Ie(wt(this,e,t))},Pt.prototype.withMutations=function(t){var e=this.asMutable();return t(e),e.wasAltered()?e.__ensureOwner(this.__ownerID):this},Pt.prototype.asMutable=function(){return this.__ownerID?this:this.__ensureOwner(new r)},Pt.prototype.asImmutable=function(){return this.__ensureOwner()},Pt.prototype.wasAltered=function(){return this.__altered},Pt.prototype.__iterator=function(t,e){return new Gt(this,t,e)},Pt.prototype.__iterate=function(t,e){var n=this,r=0;return this._root&&this._root.iterate((function(e){return r++,t(e[1],e[0],n)}),e),r},Pt.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?Yt(this.size,this._root,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},Pt.isMap=Ut;var Un="@@__IMMUTABLE_MAP__@@",Hn=Pt.prototype;Hn[Un]=!0,Hn[sn]=Hn.remove,Hn.removeIn=Hn.deleteIn,Ht.prototype.get=function(t,e,n,r){for(var i=this.entries,o=0,u=i.length;o=Vn)return $t(t,f,o,u);var _=t&&t===this.ownerID,d=_?f:i(f);return p?c?h===l-1?d.pop():d[h]=d.pop():d[h]=[o,u]:d.push([o,u]),_?(this.entries=d,this):new Ht(t,d)}},xt.prototype.get=function(t,e,n,r){void 0===e&&(e=et(n));var i=1<<((0===t?e:e>>>t)&hn),o=this.bitmap;return 0===(o&i)?r:this.nodes[ue(o&i-1)].get(t+cn,e,n,r)},xt.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=et(r));var a=(0===e?n:n>>>e)&hn,s=1<=qn)return ee(t,l,c,a,_);if(f&&!_&&2===l.length&&Qt(l[1^h]))return l[1^h];if(f&&_&&1===l.length&&Qt(_))return _;var d=t&&t===this.ownerID,v=f?_?c:c^s:c|s,y=f?_?ae(l,h,_,d):ce(l,h,d):se(l,h,_,d);return d?(this.bitmap=v,this.nodes=y,this):new xt(t,v,y)},Vt.prototype.get=function(t,e,n,r){void 0===e&&(e=et(n));var i=(0===t?e:e>>>t)&hn,o=this.nodes[i];return o?o.get(t+cn,e,n,r):r},Vt.prototype.update=function(t,e,n,r,i,o,u){void 0===n&&(n=et(r));var a=(0===e?n:n>>>e)&hn,s=i===ln,c=this.nodes,f=c[a];if(s&&!f)return this;var h=Xt(f,t,e+cn,n,r,i,o,u);if(h===f)return this;var l=this.count;if(f){if(!h&&(l--,l=0&&t>>e&hn;if(r>=this.array.length)return new le([],t);var i,o=0===r;if(e>0){var u=this.array[r];if(i=u&&u.removeBefore(t,e-cn,n),i===u&&o)return this}if(o&&!i)return this;var a=me(this,t);if(!o)for(var s=0;s>>e&hn;if(r>=this.array.length)return this;var i;if(e>0){var o=this.array[r];if(i=o&&o.removeAfter(t,e-cn,n),i===o&&r===this.array.length-1)return this}var u=me(this,t);return u.array.splice(r+1),i&&(u.array[r]=i),u};var Bn,Yn={};t(Ie,Pt),Ie.of=function(){return this(arguments)},Ie.prototype.toString=function(){return this.__toString("OrderedMap {","}")},Ie.prototype.get=function(t,e){var n=this._map.get(t);return void 0!==n?this._list.get(n)[1]:e},Ie.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._map.clear(),this._list.clear(),this):Te()},Ie.prototype.set=function(t,e){return Ae(this,t,e)},Ie.prototype.remove=function(t){return Ae(this,t,ln)},Ie.prototype.wasAltered=function(){return this._map.wasAltered()||this._list.wasAltered()},Ie.prototype.__iterate=function(t,e){var n=this;return this._list.__iterate((function(e){return e&&t(e[1],e[0],n)}),e)},Ie.prototype.__iterator=function(t,e){return this._list.fromEntrySeq().__iterator(t,e)},Ie.prototype.__ensureOwner=function(t){if(t===this.__ownerID)return this;var e=this._map.__ensureOwner(t),n=this._list.__ensureOwner(t);return t?we(e,n,t,this.__hash):(this.__ownerID=t,this._map=e,this._list=n,this)},Ie.isOrderedMap=Oe,Ie.prototype[mn]=!0,Ie.prototype[sn]=Ie.prototype.remove;var Jn;t(De,Y),De.of=function(){return this(arguments)},De.prototype.toString=function(){return this.__toString("Stack [","]")},De.prototype.get=function(t,e){var n=this._head;for(t=u(this,t);n&&t--;)n=n.next;return n?n.value:e},De.prototype.peek=function(){return this._head&&this._head.value},De.prototype.push=function(){var t=arguments;if(0===arguments.length)return this;for(var e=this.size+arguments.length,n=this._head,r=arguments.length-1;r>=0;r--)n={value:t[r],next:n};return this.__ownerID?(this.size=e,this._head=n,this.__hash=void 0,this.__altered=!0,this):ze(e,n)},De.prototype.pushAll=function(t){if(t=_(t),0===t.size)return this;at(t.size);var e=this.size,n=this._head;return t.reverse().forEach((function(t){e++,n={value:t,next:n}})),this.__ownerID?(this.size=e,this._head=n,this.__hash=void 0,this.__altered=!0,this):ze(e,n)},De.prototype.pop=function(){return this.slice(1)},De.prototype.unshift=function(){return this.push.apply(this,arguments)},De.prototype.unshiftAll=function(t){return this.pushAll(t)},De.prototype.shift=function(){return this.pop.apply(this,arguments)},De.prototype.clear=function(){return 0===this.size?this:this.__ownerID?(this.size=0,this._head=void 0,this.__hash=void 0,this.__altered=!0,this):Re()},De.prototype.slice=function(t,e){if(s(t,e,this.size))return this;var n=c(t,this.size),r=f(e,this.size);if(r!==this.size)return Y.prototype.slice.call(this,t,e);for(var i=this.size-n,o=this._head;n--;)o=o.next;return this.__ownerID?(this.size=i,this._head=o,this.__hash=void 0,this.__altered=!0,this):ze(i,o)},De.prototype.__ensureOwner=function(t){return t===this.__ownerID?this:t?ze(this.size,this._head,t,this.__hash):(this.__ownerID=t,this.__altered=!1,this)},De.prototype.__iterate=function(t,e){var n=this;if(e)return this.reverse().__iterate(t);for(var r=0,i=this._head;i&&t(i.value,r++,n)!==!1;)i=i.next;return r},De.prototype.__iterator=function(t,e){if(e)return this.reverse().__iterator(t);var n=0,r=this._head;return new b(function(){if(r){var e=r.value;return r=r.next,E(t,n++,e)}return I()})},De.isStack=Ce;var Wn="@@__IMMUTABLE_STACK__@@",Xn=De.prototype;Xn[Wn]=!0,Xn.withMutations=Hn.withMutations,Xn.asMutable=Hn.asMutable,Xn.asImmutable=Hn.asImmutable,Xn.wasAltered=Hn.wasAltered;var Qn;t(Me,J),Me.of=function(){return this(arguments)},Me.fromKeys=function(t){return this(p(t).keySeq())},Me.prototype.toString=function(){return this.__toString("Set {","}")},Me.prototype.has=function(t){return this._map.has(t)},Me.prototype.add=function(t){return je(this,this._map.set(t,!0))},Me.prototype.remove=function(t){return je(this,this._map.remove(t))},Me.prototype.clear=function(){return je(this,this._map.clear())},Me.prototype.union=function(){var t=an.call(arguments,0);return t=t.filter((function(t){return 0!==t.size})),0===t.length?this:0!==this.size||this.__ownerID||1!==t.length?this.withMutations((function(e){for(var n=0;n1?" by "+this._step:"")+" ]"},Ye.prototype.get=function(t,e){return this.has(t)?this._start+u(this,t)*this._step:e},Ye.prototype.includes=function(t){var e=(t-this._start)/this._step;return e>=0&&e=0&&nn?I():E(t,o++,u)})},Ye.prototype.equals=function(t){return t instanceof Ye?this._start===t._start&&this._end===t._end&&this._step===t._step:Be(this,t)};var ir;t(Je,R),Je.prototype.toString=function(){return 0===this.size?"Repeat []":"Repeat [ "+this._value+" "+this.size+" times ]"},Je.prototype.get=function(t,e){return this.has(t)?this._value:e},Je.prototype.includes=function(t){return W(this._value,t)},Je.prototype.slice=function(t,e){var n=this.size;return s(t,e,n)?this:new Je(this._value,f(e,n)-c(t,n))},Je.prototype.reverse=function(){return this},Je.prototype.indexOf=function(t){return W(this._value,t)?0:-1},Je.prototype.lastIndexOf=function(t){return W(this._value,t)?this.size:-1},Je.prototype.__iterate=function(t,e){for(var n=this,r=0;rthis.size?e:this.find((function(e,n){return n===t}),void 0,e)},has:function(t){return t=u(this,t),t>=0&&(void 0!==this.size?this.size===1/0||t-1&&t%1===0&&t<=Number.MAX_VALUE}var i=Function.prototype.bind;e.isString=function(t){return"string"==typeof t||"[object String]"===n(t)},e.isArray=Array.isArray||function(t){return"[object Array]"===n(t)},"function"!=typeof/./&&"object"!=typeof Int8Array?e.isFunction=function(t){return"function"==typeof t||!1}:e.isFunction=function(t){return"[object Function]"===toString.call(t)},e.isObject=function(t){var e=typeof t;return"function"===e||"object"===e&&!!t},e.extend=function(t){var e=arguments,n=arguments.length;if(!t||n<2)return t||{};for(var r=1;r0)){var e=this.reactorState.get("dirtyStores");if(0!==e.size){var n=c.default.Set().withMutations((function(n){n.union(t.observerState.get("any")),e.forEach((function(e){var r=t.observerState.getIn(["stores",e]);r&&n.union(r)}))}));n.forEach((function(e){var n=t.observerState.getIn(["observersMap",e]);if(n){var r=n.get("getter"),i=n.get("handler"),o=p.evaluate(t.prevReactorState,r),u=p.evaluate(t.reactorState,r);t.prevReactorState=o.reactorState,t.reactorState=u.reactorState;var a=o.result,s=u.result;c.default.is(a,s)||i.call(null,s)}}));var r=p.resetDirtyStores(this.reactorState);this.prevReactorState=r,this.reactorState=r}}}},{key:"batchStart",value:function(){this.__batchDepth++}},{key:"batchEnd",value:function(){if(this.__batchDepth--,this.__batchDepth<=0){this.__isDispatching=!0;try{this.__notify()}catch(t){throw this.__isDispatching=!1,t}this.__isDispatching=!1}}}]),t})();e.default=(0,y.toFactory)(g),t.exports=e.default},function(t,e,n){function r(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function i(t,e){var n={};return(0,o.each)(e,(function(e,r){n[r]=t.evaluate(e)})),n}Object.defineProperty(e,"__esModule",{value:!0});var o=n(4);e.default=function(t){return{getInitialState:function(){return i(t,this.getDataBindings())},componentDidMount:function(){var e=this;this.__unwatchFns=[],(0,o.each)(this.getDataBindings(),(function(n,i){var o=t.observe(n,(function(t){e.setState(r({},i,t))}));e.__unwatchFns.push(o)}))},componentWillUnmount:function(){for(var t=this;this.__unwatchFns.length;)t.__unwatchFns.shift()()}}},t.exports=e.default},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t,e){return new M({result:t,reactorState:e})}function o(t,e){return t.withMutations((function(t){(0,R.each)(e,(function(e,n){t.getIn(["stores",n])&&console.warn("Store already defined for id = "+n);var r=e.getInitialState();if(void 0===r&&f(t,"throwOnUndefinedStoreReturnValue"))throw new Error("Store getInitialState() must return a value, did you forget a return statement");if(f(t,"throwOnNonImmutableStore")&&!(0,D.isImmutableValue)(r))throw new Error("Store getInitialState() must return an immutable value, did you forget to call toImmutable");t.update("stores",(function(t){return t.set(n,e)})).update("state",(function(t){return t.set(n,r)})).update("dirtyStores",(function(t){return t.add(n)})).update("storeStates",(function(t){return I(t,[n])}))})),E(t)}))}function u(t,e){return t.withMutations((function(t){(0,R.each)(e,(function(e,n){t.update("stores",(function(t){return t.set(n,e)}))}))}))}function a(t,e,n){if(void 0===e&&f(t,"throwOnUndefinedActionType"))throw new Error("`dispatch` cannot be called with an `undefined` action type.");var r=t.get("state"),i=t.get("dirtyStores"),o=r.withMutations((function(r){A.default.dispatchStart(t,e,n),t.get("stores").forEach((function(o,u){var a=r.get(u),s=void 0;try{s=o.handle(a,e,n)}catch(e){throw A.default.dispatchError(t,e.message),e}if(void 0===s&&f(t,"throwOnUndefinedStoreReturnValue")){var c="Store handler must return a value, did you forget a return statement";throw A.default.dispatchError(t,c),new Error(c)}r.set(u,s),a!==s&&(i=i.add(u))})),A.default.dispatchEnd(t,r,i)})),u=t.set("state",o).set("dirtyStores",i).update("storeStates",(function(t){return I(t,i)}));return E(u)}function s(t,e){var n=[],r=(0,D.toImmutable)({}).withMutations((function(r){(0,R.each)(e,(function(e,i){var o=t.getIn(["stores",i]);if(o){var u=o.deserialize(e);void 0!==u&&(r.set(i,u),n.push(i))}}))})),i=w.default.Set(n);return t.update("state",(function(t){return t.merge(r)})).update("dirtyStores",(function(t){return t.union(i)})).update("storeStates",(function(t){return I(t,n)}))}function c(t,e,n){var r=e;(0,z.isKeyPath)(e)&&(e=(0,C.fromKeyPath)(e));var i=t.get("nextId"),o=(0,C.getStoreDeps)(e),u=w.default.Map({id:i,storeDeps:o,getterKey:r,getter:e,handler:n}),a=void 0;return a=0===o.size?t.update("any",(function(t){return t.add(i)})):t.withMutations((function(t){o.forEach((function(e){var n=["stores",e];t.hasIn(n)||t.setIn(n,w.default.Set()),t.updateIn(["stores",e],(function(t){return t.add(i)}))}))})),a=a.set("nextId",i+1).setIn(["observersMap",i],u),{observerState:a,entry:u}}function f(t,e){var n=t.getIn(["options",e]);if(void 0===n)throw new Error("Invalid option: "+e);return n}function h(t,e,n){var r=t.get("observersMap").filter((function(t){var r=t.get("getterKey"),i=!n||t.get("handler")===n;return!!i&&((0,z.isKeyPath)(e)&&(0,z.isKeyPath)(r)?(0,z.isEqual)(e,r):e===r)}));return t.withMutations((function(t){r.forEach((function(e){return l(t,e)}))}))}function l(t,e){return t.withMutations((function(t){var n=e.get("id"),r=e.get("storeDeps");0===r.size?t.update("any",(function(t){return t.remove(n)})):r.forEach((function(e){t.updateIn(["stores",e],(function(t){return t?t.remove(n):t}))})),t.removeIn(["observersMap",n])}))}function p(t){var e=t.get("state");return t.withMutations((function(t){var n=t.get("stores"),r=n.keySeq().toJS();n.forEach((function(n,r){var i=e.get(r),o=n.handleReset(i);if(void 0===o&&f(t,"throwOnUndefinedStoreReturnValue"))throw new Error("Store handleReset() must return a value, did you forget a return statement");if(f(t,"throwOnNonImmutableStore")&&!(0,D.isImmutableValue)(o))throw new Error("Store reset state must be an immutable value, did you forget to call toImmutable");t.setIn(["state",r],o)})),t.update("storeStates",(function(t){return I(t,r)})),v(t)}))}function _(t,e){var n=t.get("state");if((0,z.isKeyPath)(e))return i(n.getIn(e),t);if(!(0,C.isGetter)(e))throw new Error("evaluate must be passed a keyPath or Getter");if(g(t,e))return i(b(t,e),t);var r=(0,C.getDeps)(e).map((function(e){return _(t,e).result})),o=(0,C.getComputeFn)(e).apply(null,r);return i(o,S(t,e,o))}function d(t){var e={};return t.get("stores").forEach((function(n,r){var i=t.getIn(["state",r]),o=n.serialize(i);void 0!==o&&(e[r]=o)})),e}function v(t){return t.set("dirtyStores",w.default.Set())}function y(t){return t}function m(t,e){var n=y(e);return t.getIn(["cache",n])}function g(t,e){var n=m(t,e);if(!n)return!1;var r=n.get("storeStates");return 0!==r.size&&r.every((function(e,n){return t.getIn(["storeStates",n])===e}))}function S(t,e,n){var r=y(e),i=t.get("dispatchId"),o=(0,C.getStoreDeps)(e),u=(0,D.toImmutable)({}).withMutations((function(e){o.forEach((function(n){var r=t.getIn(["storeStates",n]);e.set(n,r)}))}));return t.setIn(["cache",r],w.default.Map({value:n,storeStates:u,dispatchId:i}))}function b(t,e){var n=y(e);return t.getIn(["cache",n,"value"])}function E(t){return t.update("dispatchId",(function(t){return t+1}))}function I(t,e){return t.withMutations((function(t){e.forEach((function(e){var n=t.has(e)?t.get(e)+1:1;t.set(e,n)}))}))}Object.defineProperty(e,"__esModule",{value:!0}),e.registerStores=o,e.replaceStores=u,e.dispatch=a,e.loadState=s,e.addObserver=c,e.getOption=f,e.removeObserver=h,e.removeObserverByEntry=l,e.reset=p,e.evaluate=_,e.serialize=d,e.resetDirtyStores=v;var O=n(3),w=r(O),T=n(9),A=r(T),D=n(5),C=n(10),z=n(11),R=n(4),M=w.default.Record({result:null,reactorState:null})},function(t,e,n){var r=n(8);e.dispatchStart=function(t,e,n){(0,r.getOption)(t,"logDispatches")&&console.group&&(console.groupCollapsed("Dispatch: %s",e),console.group("payload"),console.debug(n),console.groupEnd())},e.dispatchError=function(t,e){(0,r.getOption)(t,"logDispatches")&&console.group&&(console.debug("Dispatch error: "+e),console.groupEnd())},e.dispatchEnd=function(t,e,n){(0,r.getOption)(t,"logDispatches")&&console.group&&((0,r.getOption)(t,"logDirtyStores")&&console.log("Stores updated:",n.toList().toJS()),(0,r.getOption)(t,"logAppState")&&console.debug("Dispatch done, new state: ",e.toJS()),console.groupEnd())}},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t){return(0,l.isArray)(t)&&(0,l.isFunction)(t[t.length-1])}function o(t){return t[t.length-1]}function u(t){return t.slice(0,t.length-1)}function a(t,e){e||(e=h.default.Set());var n=h.default.Set().withMutations((function(e){if(!i(t))throw new Error("getFlattenedDeps must be passed a Getter");u(t).forEach((function(t){if((0,p.isKeyPath)(t))e.add((0,f.List)(t));else{if(!i(t))throw new Error("Invalid getter, each dependency must be a KeyPath or Getter");e.union(a(t))}}))}));return e.union(n)}function s(t){if(!(0,p.isKeyPath)(t))throw new Error("Cannot create Getter from KeyPath: "+t);return[t,_]}function c(t){if(t.hasOwnProperty("__storeDeps"))return t.__storeDeps;var e=a(t).map((function(t){return t.first()})).filter((function(t){return!!t}));return Object.defineProperty(t,"__storeDeps",{enumerable:!1,configurable:!1,writable:!1,value:e}),e}Object.defineProperty(e,"__esModule",{value:!0});var f=n(3),h=r(f),l=n(4),p=n(11),_=function(t){return t};e.default={isGetter:i,getComputeFn:o,getFlattenedDeps:a,getStoreDeps:c,getDeps:u,fromKeyPath:s},t.exports=e.default},function(t,e,n){function r(t){return t&&t.__esModule?t:{default:t}}function i(t){return(0,s.isArray)(t)&&!(0,s.isFunction)(t[t.length-1])}function o(t,e){var n=a.default.List(t),r=a.default.List(e);return a.default.is(n,r)}Object.defineProperty(e,"__esModule",{value:!0}),e.isKeyPath=i,e.isEqual=o;var u=n(3),a=r(u),s=n(4)},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var r=n(3),i=(0,r.Map)({logDispatches:!1,logAppState:!1,logDirtyStores:!1,throwOnUndefinedActionType:!1,throwOnUndefinedStoreReturnValue:!1,throwOnNonImmutableStore:!1,throwOnDispatchInDispatch:!1});e.PROD_OPTIONS=i;var o=(0,r.Map)({logDispatches:!0,logAppState:!0,logDirtyStores:!0,throwOnUndefinedActionType:!0,throwOnUndefinedStoreReturnValue:!0,throwOnNonImmutableStore:!0,throwOnDispatchInDispatch:!0});e.DEBUG_OPTIONS=o;var u=(0,r.Record)({dispatchId:0,state:(0,r.Map)(),stores:(0,r.Map)(),cache:(0,r.Map)(),storeStates:(0,r.Map)(),dirtyStores:(0,r.Set)(),debug:!1,options:i});e.ReactorState=u;var a=(0,r.Record)({any:(0,r.Set)(),stores:(0,r.Map)({}),observersMap:(0,r.Map)({}),nextId:1});e.ObserverState=a}])}))})),Ne=t(je),ke=function(t){var e,n={};if(!(t instanceof Object)||Array.isArray(t))throw new Error("keyMirror(...): Argument must be an object.");for(e in t)t.hasOwnProperty(e)&&(n[e]=e);return n},Pe=ke,Ue=Pe({VALIDATING_AUTH_TOKEN:null,VALID_AUTH_TOKEN:null,INVALID_AUTH_TOKEN:null,LOG_OUT:null}),He=Ne.Store,xe=Ne.toImmutable,Ve=new He({getInitialState:function(){return xe({isValidating:!1,authToken:!1,host:null,isInvalid:!1,errorMessage:""})},initialize:function(){this.on(Ue.VALIDATING_AUTH_TOKEN,n),this.on(Ue.VALID_AUTH_TOKEN,r),this.on(Ue.INVALID_AUTH_TOKEN,i)}}),qe=Ne.Store,Fe=Ne.toImmutable,Ge=new qe({getInitialState:function(){return Fe({authToken:null,host:""})},initialize:function(){this.on(Ue.VALID_AUTH_TOKEN,o),this.on(Ue.LOG_OUT,u)}}),Ke=Ne.Store,Be=new Ke({getInitialState:function(){return!0},initialize:function(){this.on(Ue.VALID_AUTH_TOKEN,a)}}),Ye=Pe({STREAM_START:null,STREAM_STOP:null,STREAM_ERROR:null}),Je=Ne.Store,We=Ne.toImmutable,Xe=new Je({getInitialState:function(){return We({isStreaming:!1,hasError:!1})},initialize:function(){this.on(Ye.STREAM_START,s),this.on(Ye.STREAM_ERROR,c),this.on(Ye.LOG_OUT,f)}}),Qe=1,Ze=2,$e=3,tn=function(t,e){this.url=t,this.options=e||{},this.commandId=1,this.commands={},this.connectionTries=0,this.eventListeners={},this.closeRequested=!1};tn.prototype.addEventListener=function(t,e){var n=this.eventListeners[t];n||(n=this.eventListeners[t]=[]),n.push(e)},tn.prototype.fireEvent=function(t){var e=this;(this.eventListeners[t]||[]).forEach((function(t){return t(e)}))},tn.prototype.connect=function(){var t=this;return new Promise(function(e,n){var r=t.commands;Object.keys(r).forEach((function(t){var e=r[t];e.reject&&e.reject(S($e,"Connection lost"))}));var i=!1;t.connectionTries+=1,t.socket=new WebSocket(t.url),t.socket.addEventListener("open",(function(){t.connectionTries=0})),t.socket.addEventListener("message",(function(o){var u=JSON.parse(o.data);switch(u.type){case"event":t.commands[u.id].eventCallback(u.event);break;case"result":u.success?t.commands[u.id].resolve(u):t.commands[u.id].reject(u.error),delete t.commands[u.id];break;case"pong":break;case"auth_required":t.sendMessage(h(t.options.authToken));break;case"auth_invalid":n(Ze),i=!0;break;case"auth_ok":e(t),t.fireEvent("ready"),t.commandId=1,t.commands={},Object.keys(r).forEach((function(e){var n=r[e];n.eventType&&t.subscribeEvents(n.eventCallback,n.eventType).then((function(t){n.unsubscribe=t}))}))}})),t.socket.addEventListener("close",(function(){if(!i&&!t.closeRequested){0===t.connectionTries?t.fireEvent("disconnected"):n(Qe);var e=1e3*Math.min(t.connectionTries,5);setTimeout((function(){return t.connect()}),e)}}))})},tn.prototype.close=function(){this.closeRequested=!0,this.socket.close()},tn.prototype.getStates=function(){return this.sendMessagePromise(l()).then(b)},tn.prototype.getServices=function(){return this.sendMessagePromise(_()).then(b)},tn.prototype.getPanels=function(){return this.sendMessagePromise(d()).then(b)},tn.prototype.getConfig=function(){return this.sendMessagePromise(p()).then(b)},tn.prototype.callService=function(t,e,n){return this.sendMessagePromise(v(t,e,n))},tn.prototype.subscribeEvents=function(t,e){var n=this;return this.sendMessagePromise(y(e)).then((function(r){var i={eventCallback:t,eventType:e,unsubscribe:function(){return n.sendMessagePromise(m(r.id)).then((function(){delete n.commands[r.id]}))}};return n.commands[r.id]=i,function(){return i.unsubscribe()}}))},tn.prototype.ping=function(){return this.sendMessagePromise(g())},tn.prototype.sendMessage=function(t){this.socket.send(JSON.stringify(t))},tn.prototype.sendMessagePromise=function(t){var e=this;return new Promise(function(n,r){e.commandId+=1;var i=e.commandId;t.id=i,e.commands[i]={resolve:n,reject:r},e.sendMessage(t)})};var en=Pe({API_FETCH_ALL_START:null,API_FETCH_ALL_SUCCESS:null,API_FETCH_ALL_FAIL:null,SYNC_SCHEDULED:null,SYNC_SCHEDULE_CANCELLED:null}),nn=Ne.Store,rn=new nn({getInitialState:function(){return!0},initialize:function(){this.on(en.API_FETCH_ALL_START,(function(){return!0})),this.on(en.API_FETCH_ALL_SUCCESS,(function(){return!1})),this.on(en.API_FETCH_ALL_FAIL,(function(){return!1})),this.on(en.LOG_OUT,(function(){return!1}))}}),on=I,un=Pe({API_FETCH_SUCCESS:null,API_FETCH_START:null,API_FETCH_FAIL:null,API_SAVE_SUCCESS:null,API_SAVE_START:null,API_SAVE_FAIL:null,API_DELETE_SUCCESS:null,API_DELETE_START:null,API_DELETE_FAIL:null,LOG_OUT:null}),an=Ne.Store,sn=Ne.toImmutable,cn=new an({getInitialState:function(){return sn({})},initialize:function(){var t=this;this.on(un.API_FETCH_SUCCESS,O),this.on(un.API_SAVE_SUCCESS,O),this.on(un.API_DELETE_SUCCESS,w),this.on(un.LOG_OUT,(function(){return t.getInitialState()}))}}),fn=Object.prototype.hasOwnProperty,hn=Object.prototype.propertyIsEnumerable,ln=A()?Object.assign:function(t,e){for(var n,r,i=arguments,o=T(t),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 Iwb0E00EuBuO#lD@ literal 33524 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,t):(this._twiddle.textContent=this._twiddleContent++,this._callbacks.push(e),this._currVal++)},cancel:function(e){if(e<0)clearTimeout(~e);else{var t=e-this._lastVal;if(t>=0){if(!this._callbacks[t])throw"invalid async handle: "+e;this._callbacks[t]=null}}},_atEndOfMicrotask:function(){for(var e=this._callbacks.length,t=0;t \ No newline at end of file +this.currentTarget=t,this.defaultPrevented=!1,this.eventPhase=Event.AT_TARGET,this.timeStamp=Date.now()},i=window.Element.prototype.animate;window.Element.prototype.animate=function(n,r){var o=i.call(this,n,r);o._cancelHandlers=[],o.oncancel=null;var a=o.cancel;o.cancel=function(){a.call(this);var i=new e(this,null,t()),n=this._cancelHandlers.concat(this.oncancel?[this.oncancel]:[]);setTimeout(function(){n.forEach(function(t){t.call(i.target,i)})},0)};var s=o.addEventListener;o.addEventListener=function(t,e){"function"==typeof e&&"cancel"==t?this._cancelHandlers.push(e):s.call(this,t,e)};var u=o.removeEventListener;return o.removeEventListener=function(t,e){if("cancel"==t){var i=this._cancelHandlers.indexOf(e);i>=0&&this._cancelHandlers.splice(i,1)}else u.call(this,t,e)},o}}}(),function(t){var e=document.documentElement,i=null,n=!1;try{var r=getComputedStyle(e).getPropertyValue("opacity"),o="0"==r?"1":"0";i=e.animate({opacity:[o,o]},{duration:1}),i.currentTime=0,n=getComputedStyle(e).getPropertyValue("opacity")==o}catch(t){}finally{i&&i.cancel()}if(!n){var a=window.Element.prototype.animate;window.Element.prototype.animate=function(e,i){return window.Symbol&&Symbol.iterator&&Array.prototype.from&&e[Symbol.iterator]&&(e=Array.from(e)),Array.isArray(e)||null===e||(e=t.convertToArrayForm(e)),a.call(this,e,i)}}}(c),!function(t,e,i){function n(t){var i=e.timeline;i.currentTime=t,i._discardAnimations(),0==i._animations.length?o=!1:requestAnimationFrame(n)}var r=window.requestAnimationFrame;window.requestAnimationFrame=function(t){return r(function(i){e.timeline._updateAnimationsPromises(),t(i),e.timeline._updateAnimationsPromises()})},e.AnimationTimeline=function(){this._animations=[],this.currentTime=void 0},e.AnimationTimeline.prototype={getAnimations:function(){return this._discardAnimations(),this._animations.slice()},_updateAnimationsPromises:function(){e.animationsWithPromises=e.animationsWithPromises.filter(function(t){return t._updatePromises()})},_discardAnimations:function(){this._updateAnimationsPromises(),this._animations=this._animations.filter(function(t){return"finished"!=t.playState&&"idle"!=t.playState})},_play:function(t){var i=new e.Animation(t,this);return this._animations.push(i),e.restartWebAnimationsNextTick(),i._updatePromises(),i._animation.play(),i._updatePromises(),i},play:function(t){return t&&t.remove(),this._play(t)}};var o=!1;e.restartWebAnimationsNextTick=function(){o||(o=!0,requestAnimationFrame(n))};var a=new e.AnimationTimeline;e.timeline=a;try{Object.defineProperty(window.document,"timeline",{configurable:!0,get:function(){return a}})}catch(t){}try{window.document.timeline=a}catch(t){}}(c,e,f),function(t,e,i){e.animationsWithPromises=[],e.Animation=function(e,i){if(this.id="",e&&e._id&&(this.id=e._id),this.effect=e,e&&(e._animation=this),!i)throw new Error("Animation with null timeline is not supported");this._timeline=i,this._sequenceNumber=t.sequenceNumber++,this._holdTime=0,this._paused=!1,this._isGroup=!1,this._animation=null,this._childAnimations=[],this._callback=null,this._oldPlayState="idle",this._rebuildUnderlyingAnimation(),this._animation.cancel(),this._updatePromises()},e.Animation.prototype={_updatePromises:function(){var t=this._oldPlayState,e=this.playState;return this._readyPromise&&e!==t&&("idle"==e?(this._rejectReadyPromise(),this._readyPromise=void 0):"pending"==t?this._resolveReadyPromise():"pending"==e&&(this._readyPromise=void 0)),this._finishedPromise&&e!==t&&("idle"==e?(this._rejectFinishedPromise(),this._finishedPromise=void 0):"finished"==e?this._resolveFinishedPromise():"finished"==t&&(this._finishedPromise=void 0)),this._oldPlayState=this.playState,this._readyPromise||this._finishedPromise},_rebuildUnderlyingAnimation:function(){this._updatePromises();var t,i,n,r,o=!!this._animation;o&&(t=this.playbackRate,i=this._paused,n=this.startTime,r=this.currentTime,this._animation.cancel(),this._animation._wrapper=null,this._animation=null),(!this.effect||this.effect instanceof window.KeyframeEffect)&&(this._animation=e.newUnderlyingAnimationForKeyframeEffect(this.effect),e.bindAnimationForKeyframeEffect(this)),(this.effect instanceof window.SequenceEffect||this.effect instanceof window.GroupEffect)&&(this._animation=e.newUnderlyingAnimationForGroup(this.effect),e.bindAnimationForGroup(this)),this.effect&&this.effect._onsample&&e.bindAnimationForCustomEffect(this),o&&(1!=t&&(this.playbackRate=t),null!==n?this.startTime=n:null!==r?this.currentTime=r:null!==this._holdTime&&(this.currentTime=this._holdTime),i&&this.pause()),this._updatePromises()},_updateChildren:function(){if(this.effect&&"idle"!=this.playState){var t=this.effect._timing.delay;this._childAnimations.forEach(function(i){this._arrangeChildren(i,t),this.effect instanceof window.SequenceEffect&&(t+=e.groupChildDuration(i.effect))}.bind(this))}},_setExternalAnimation:function(t){if(this.effect&&this._isGroup)for(var e=0;e \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/frontend.html.gz b/homeassistant/components/frontend/www_static/frontend.html.gz index b1488e61a11ee39c694803a710a4e6b8eea2e090..7d29d3b9612a0a75b3204479f3f6ee038cf9e6bf 100644 GIT binary patch delta 19846 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 delta 19541 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 E0Ik9$LI3~& diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 336e974fe6f..b8a7c6624d5 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 336e974fe6f4196aaf0b309e805a009ef0fdfd66 +Subproject commit b8a7c6624d54d3f579ff22079c9dc01843a0fc6e diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html index e4fd1211753..9ce5304213e 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-service.html.gz index 2419c25adbd0c227748e2991b75bdd3295e45bd4..e9007a00c9334d6e15c94e2b0ac8bd11bfbec312 100644 GIT binary patch delta 8811 zcmV-xB9z_aiUEX+0S6z82ndk!P_YLzBY%kwgflw8!wYd?_!OI$u}ymLv$$EN0lyr? zXrgX)w`YNPQaNd>CCISjkT*e3qh7HO z>QjC2e2_dNc2GB8u0KP{8-~}t`Ew&e@U!1RF$f#yfL+#9@#(QK3ZQJHB1(KjCx2#X zevEp4sn|EO6(i&&idp~<9~Pu+8fJFcpk2-tLHN8HJ}-JII?NBvVnWQ0T*@$YaJq}- z5AxXMvQv))*7%s?)W`D4l6(V0jmj)KbpL_zAi8MHnX(g?4M`V6?Q6$D3O@`co%VJf zvt3b{K)3Xmd})tP#fX9$+NsKhjen8s8ulIz=j*GtjLp%VX=1Fisv5Hsgsh25Ajb%O z&7HUqz@f!Wyod`POGMb)Y`I!;$fz`mGtX+orI`pkd0hKwL_AA(=R4zz)H<*6Ds?#y z3hmgQgt>3IRTx=KT!@?WBALNX=bk*~ZKbhNdC$oznof!NTkOExHc1K#Eq@;jP3yg*mdJLG z(vjYXi+d6%vU1x^s9gls{G?9ClRO#Az*-Li;3h?^EBj_iuZ}~#9yBrI*ixh+;Kld4 zplO<8(oI$Z#`{IT?s$JT9Xs7KG&Ai22aTre zsGYKd14&H;$CBMFxqrqqKV#=9cW$zMo4(Vo$aG#){PD9Fi@cbJ!hb1BGU+)P)!mu7 z#G2T(+< zdH!31ci*3Vx)EWpk5)> zt@Xm;+3Lqu|=b(prfk5;+y(zr#MCk>EP z8CZ$O0mLZ|%L?SgDWYHylh4ixxr+FAW=pTR*9rGBQ%E6PK!2y3s*yb-?hwTyvbB#i z#I!l^GAzdqJ(OoJZ-{$UF4Z0vW?582m|Q*LDSPDUDBPK6i!4S{eClT?4f|F8MeeC6 z7GLGso3f^mpMMs4@`i3idLv20!+HwX@ZuA@zqp|LX=lQF^j!NAHgi3xGm-PuVVhlY z-=n?m9twZd4t;YPCBLC(fkdn6Rxe=*V#)_suYMw)S(md7-6GLMhE=)CYLK;+yMcTq zs2OAf_3BMq4KCSWSy#6?(9uC&4hk|S!SDjf+n*veXMda`*JhLouLhladZ2Z&h9SUl z6pLa8?u$uvOT3=x;hr@I7(q^)3*C8;>jCiHFtL4D@E{ja{zPTP+KQO4VifOrL_63R ziyicg-R1@;aR?2)%Ji7589gMShG&)g{h=H0e(%u%&n)6ud_I)O5kQIyl{lYUt zd3MvZIVmQdwK`jzBcE37?^m0vBdP`FZ4?Q##6j;spA$nss&-mu{e|Gl2N(j);MhFj z7Y)CbsEf{70+U@HxkaRyQEI-SMuD^P93OSiV@*Ao4Fm@z?E93&u(fs*MlXde$WT&t z3jx;NG*dVT>t0W3V5NjZ7pVg2F=wAi+2BG&iKzx zk)!!g84nusq)q6J?$h_eHOG9)!Z~rDQxcj{BnZ#E@9*TC3=}{DiX)|1Dmcam+4`(F zR}!L##rRu3|BQkxci~61q5d{|43tH>tS`9c4m;SalGOJM^*t_9LJd&d@L}!H@s#&D zavBqVT|B8V?P+nGyZ5bvW8eHvJP;Y$zDyjRC*GnS{}W&31B|Gk>kvIpQS_O@bMuCy z$>y}U`5qonvR%2xP4c^4`T3NuC}7Q|gX2ZqD7MHZlSl|Lga(MjjVlP*rz>yd1re=+ z5~gzKM@dbdBaV9C(L`No_i~MLpwM?Lqt0r7uPbuPLICJE?B+!Dm09mFijr|ak8Y5^ znxWD)c1hPkT@|RW7SH<8GjbzGO`|)gI$W^G+~Nh%0DphrBh|3)E)yVgdH}`n^ojGn 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 N{{Xe+tOk`7002MyPgwu} delta 2236 zcmV;t2t)Ul5|a{tABzYGiBC#c0t0hpa&~EBWnXu1a%*LBE^2cCrC9lM+qf0}R}@ZH zA!~{vz!O$AnQS)Grp+}uCO^1Y4~_?k2}PstP3wArnM37nKG@r^ z;LGDLR!w>9-Jbrmg6qM1Ft~!-wzgEYDRd#Z{m=6&sLV57mV(Q#F8Id#u8RiVuG;x_ z^*isrJ2yf9;45x8{%==KVAp)ZXZP1}$u~DkIEP#R$S1*Y$F z;dDBEBffxtG(CF#D=#Ranwj}$D=%3y1&a=8Qh~?-5I_sP}e7P*wj*h>y zb>;X^S16<@{@bmcJHG;Npcy!4=GOB?t!~c$`Tos+>%eACHA5@1jPhrRx!A zGR%a3ra95TGDfr@Nlr76gyv~ZlZ_e{5zQie5v92j840yiI?)*osisMupH|aCb5%$f z(J-bV&?wKeVv!O_By*KzdB{+xO4wEt(?l`|nGR_f3Wa*JI97^Aie;(d4`?#nz$i@s z?P5gAIL(rjWP}Nwpl2k?(=drQda@in&GM9grwLl1^HfG!r8;JLA{DR)fHSaImR41U z@r=31bSA@Gq$=eKeM}k4nSwYBH>z@;0x%W}B9({}5$1$4CeR$lNCN7(Dr_sGNQ9E7 z5ynCa$U{vtp`ug?N#iJnd<&YQ6aa{fq8zsZ3rU_J0xC+Rh@*`L3s51)vTk6MC@rXe ziXcfd%~h0f9b%HISWre0LKS>zZ7_He(k#S?rzC=i>o{gQm01==DPpxRcjLf_OOgme z;wT{z)OVv1gIMMRiJKNIz`n9a>vRwfcH@>~-t082KGbchu} zgp9CI35|ay>lLVCwO9+&fDwsF7Gi=+s%4U=Nk|~eFhu}m|4i6Bn5|0Qtfg^(%>Ilq zl?cH#c9K+c>;zoo3i3E2a#vbm`}SD#EBi3QuJaB52Fq%Oa$>?*7>OJqLW6h)G!M~3 zVN;TjEIBDBz<+GpjA@i$B4nr)tXqIZBY+B-vQ+9lh>8WDL5oDtsLKUH!!NNcZ=ksp zv$Zumim|gPB1s-43X201jG`$wED8Y|GvAeV4MNt7WnE$SZAWEckl2f=FM}N0U!9ummd?A z@&qOU+>;pvDu3s_MtP`lz=uP*BMB!aOX}SF@xzrti%cu$XVdND6KCjH7|x)QwStfD zUOd|b#x>rVGj)!=sXWh@d*&AHTlD4A979pfG) z4xzdzQS-5lCcu%Sxw(5~Hm@FG=Ykdo)Qj-5*Nw6#b$zLeYNM)uM$_))&z!gO4uif- zE_dq0@o`vgKh&G#YCAMup|<_;>c9XCotat#{R)2wmc?D<{I1B#x*zl~Kc@RB?DBn^ zFpD3N4S)IVZ=7ROP?-?a>aYhIX-l_^TM^Pml| zzAJazC{7;?4v!=Ewr(Rdc-z#AqJ;p}yHA^j-vmg*3-=zH!4)r8fXA475v;l@z%U~W zwt}|dL?2xX<2(4z%4R_2e@EyPdR_3cJ$G8Pe}9DI@~o&F1g86QaMIcF2VrZ!7RyhF zNS_S$1OEh^_8fDCVcN&DkM!oubkf1e|AG67!(Me1?dl;Y?b&Y!&i+h;d;SPevMekI z;V&;1KY^+{9_{0VRycou{=w;5Thqrc=#NNi5V2BDb|&}k8+73zCh{g`dOr$%8g&hn zPk*s2kd*qFZ1M`SC_U5o63FstX`F> z`uAfquxP`b4qfBv`j^%j*nZVpa6b6u&EtKvksa4p0NdrRAWm1ra@Ed{G>%DspMQYC zL$+AoRJ6AA{M~+WWGI{0*ROZ3MO>uB!jzV_4`DvMo9XUW9L#nouJ9PPzJjs0F6&zw z`(v+O?rvMWhw6Rzh6ekDz5Y0K_4Eyr(|uzN0qgkQeUB{b7Tkm79^%d%$#@=gYpyrJFE(b_TKm+g-fTO3 Date: Tue, 13 Dec 2016 23:46:27 -0800 Subject: [PATCH 102/141] Fix hue groups on older hubs (#4884) --- homeassistant/components/light/hue.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/light/hue.py b/homeassistant/components/light/hue.py index 74247ad24ef..259553cc620 100644 --- a/homeassistant/components/light/hue.py +++ b/homeassistant/components/light/hue.py @@ -143,10 +143,13 @@ def setup_bridge(host, hass, add_devices, filename, allow_unreachable): lights = {} lightgroups = {} + skip_groups = False @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update_lights(): """Update the Hue light objects with latest info from the bridge.""" + nonlocal skip_groups + try: api = bridge.get_api() except socket.error: @@ -160,7 +163,10 @@ def setup_bridge(host, hass, add_devices, filename, allow_unreachable): _LOGGER.error("Got unexpected result from Hue API") return - api_groups = api.get('groups') + if skip_groups: + api_groups = {} + else: + api_groups = api.get('groups') if not isinstance(api_groups, dict): _LOGGER.error("Got unexpected result from Hue API") @@ -185,6 +191,12 @@ def setup_bridge(host, hass, add_devices, filename, allow_unreachable): lights[light_id].schedule_update_ha_state() for lightgroup_id, info in api_groups.items(): + if 'state' not in info: + _LOGGER.warning('Group info does not contain state. ' + 'Please update your hub.') + skip_groups = True + break + if lightgroup_id not in lightgroups: lightgroups[lightgroup_id] = HueLight( int(lightgroup_id), info, bridge, update_lights, From be552a59c956d70405571ae532bb6582fa2082e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Wed, 14 Dec 2016 18:45:05 +0100 Subject: [PATCH 103/141] Bug in rpi_camera --- homeassistant/components/camera/rpi_camera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/camera/rpi_camera.py b/homeassistant/components/camera/rpi_camera.py index c5603dac142..b42c62e56d0 100644 --- a/homeassistant/components/camera/rpi_camera.py +++ b/homeassistant/components/camera/rpi_camera.py @@ -39,7 +39,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_FILE_PATH): cv.string, vol.Optional(CONF_HORIZONTAL_FLIP, default=DEFAULT_HORIZONTAL_FLIP): vol.All(vol.Coerce(int), vol.Range(min=0, max=1)), - vol.Optional(CONF_IMAGE_HEIGHT, default=DEFAULT_HORIZONTAL_FLIP): + vol.Optional(CONF_IMAGE_HEIGHT, default=DEFAULT_IMAGE_HEIGHT): vol.Coerce(int), vol.Optional(CONF_IMAGE_QUALITY, default=DEFAULT_IMAGE_QUALITIY): vol.All(vol.Coerce(int), vol.Range(min=0, max=100)), From a359d21799edbfa3819e9073f0f0874ebae0c605 Mon Sep 17 00:00:00 2001 From: Valentin Alexeev Date: Wed, 14 Dec 2016 20:05:03 +0200 Subject: [PATCH 104/141] [media_player.sonos] Source selection from favorites (#4804) --- .../components/media_player/sonos.py | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/media_player/sonos.py b/homeassistant/components/media_player/sonos.py index c6e9c1e6655..e9653d2a8d8 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -298,6 +298,8 @@ class SonosDevice(MediaPlayerDevice): self._last_avtransport_event = None self._is_playing_line_in = None self._is_playing_tv = None + self._favorite_sources = None + self._source_name = None self.soco_snapshot = Snapshot(self._player) @property @@ -443,6 +445,8 @@ class SonosDevice(MediaPlayerDevice): else: media_artist = SUPPORT_SOURCE_LINEIN + source_name = media_artist + media_album_name = None media_title = None media_image_url = None @@ -456,6 +460,16 @@ class SonosDevice(MediaPlayerDevice): support_stop = False support_pause = False + source_name = 'Radio' + # Check if currently playing radio station is in favorites + favs = self._player.get_sonos_favorites()['favorites'] + favc = [ + fav for fav in favs if fav['uri'] == current_media_uri + ] + if len(favc) == 1: + src = favc.pop() + source_name = src['title'] + # for radio streams we set the radio station name as the # title. if media_artist and media_title: @@ -592,6 +606,7 @@ class SonosDevice(MediaPlayerDevice): self._support_pause = support_pause self._is_playing_tv = is_playing_tv self._is_playing_line_in = is_playing_line_in + self._source_name = source_name # update state of the whole group # pylint: disable=protected-access @@ -601,6 +616,8 @@ class SonosDevice(MediaPlayerDevice): if self._queue is None and self.entity_id is not None: self._subscribe_to_player_events() + favs = self._player.get_sonos_favorites().get('favorites', []) + self._favorite_sources = [fav['title'] for fav in favs] else: self._player_volume = None self._player_volume_muted = None @@ -624,6 +641,8 @@ class SonosDevice(MediaPlayerDevice): self._support_pause = False self._is_playing_tv = False self._is_playing_line_in = False + self._favorite_sources = None + self._source_name = None self._last_avtransport_event = None @@ -771,10 +790,6 @@ class SonosDevice(MediaPlayerDevice): supported = SUPPORT_SONOS - if not self.source_list: - # some devices do not allow source selection - supported = supported ^ SUPPORT_SELECT_SOURCE - if not self._support_previous_track: supported = supported ^ SUPPORT_PREVIOUS_TRACK @@ -808,19 +823,31 @@ class SonosDevice(MediaPlayerDevice): def select_source(self, source): """Select input source.""" if source == SUPPORT_SOURCE_LINEIN: + self._source_name = SUPPORT_SOURCE_LINEIN self._player.switch_to_line_in() elif source == SUPPORT_SOURCE_TV: + self._source_name = SUPPORT_SOURCE_TV self._player.switch_to_tv() + else: + favorites = self._player.get_sonos_favorites()['favorites'] + fav = [fav for fav in favorites if fav['title'] == source] + if len(fav) == 1: + src = fav.pop() + self._source_name = src['title'] + self._player.play_uri(src['uri'], src['meta'], src['title']) @property def source_list(self): """List of available input sources.""" model_name = self._speaker_info['model_name'] + sources = self._favorite_sources + if 'PLAY:5' in model_name: - return [SUPPORT_SOURCE_LINEIN] + sources += [SUPPORT_SOURCE_LINEIN] elif 'PLAYBAR' in model_name: - return [SUPPORT_SOURCE_LINEIN, SUPPORT_SOURCE_TV] + sources += [SUPPORT_SOURCE_LINEIN, SUPPORT_SOURCE_TV] + return sources @property def source(self): @@ -828,12 +855,7 @@ class SonosDevice(MediaPlayerDevice): if self._coordinator: return self._coordinator.source else: - if self._is_playing_line_in: - return SUPPORT_SOURCE_LINEIN - elif self._is_playing_tv: - return SUPPORT_SOURCE_TV - - return None + return self._source_name def turn_off(self): """Turn off media player.""" From 6d2de67620451a725d0b949a7992d653d531c03e Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Wed, 14 Dec 2016 22:32:20 +0100 Subject: [PATCH 105/141] TTS add google language list for config check (#4912) * Add config check for language * update default * move language from component to platform * fix lint --- homeassistant/components/tts/__init__.py | 6 ++---- homeassistant/components/tts/google.py | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/tts/__init__.py b/homeassistant/components/tts/__init__.py index 0e75de88cc5..d0faa60684f 100644 --- a/homeassistant/components/tts/__init__.py +++ b/homeassistant/components/tts/__init__.py @@ -41,7 +41,6 @@ CONF_TIME_MEMORY = 'time_memory' DEFAULT_CACHE = True DEFAULT_CACHE_DIR = "tts" -DEFAULT_LANG = 'en' DEFAULT_TIME_MEMORY = 300 SERVICE_SAY = 'say' @@ -53,7 +52,6 @@ ATTR_CACHE = 'cache' _RE_VOICE_FILE = re.compile(r"([a-f0-9]{40})_([a-z]+)\.[a-z0-9]{3,4}") PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_LANG, default=DEFAULT_LANG): cv.string, vol.Optional(CONF_CACHE, default=DEFAULT_CACHE): cv.boolean, vol.Optional(CONF_CACHE_DIR, default=DEFAULT_CACHE_DIR): cv.string, vol.Optional(CONF_TIME_MEMORY, default=DEFAULT_TIME_MEMORY): @@ -79,7 +77,7 @@ def async_setup(hass, config): conf = config[DOMAIN][0] if len(config.get(DOMAIN, [])) > 0 else {} use_cache = conf.get(CONF_CACHE, DEFAULT_CACHE) cache_dir = conf.get(CONF_CACHE_DIR, DEFAULT_CACHE_DIR) - time_memory = conf.get(CONF_TIME_MEMORY, DEFAULT_LANG) + time_memory = conf.get(CONF_TIME_MEMORY, DEFAULT_TIME_MEMORY) yield from tts.async_init_cache(use_cache, cache_dir, time_memory) except (HomeAssistantError, KeyError) as err: @@ -379,7 +377,7 @@ class Provider(object): """Represent a single provider.""" hass = None - language = DEFAULT_LANG + language = None def get_tts_audio(self, message): """Load tts audio file from provider.""" diff --git a/homeassistant/components/tts/google.py b/homeassistant/components/tts/google.py index b271b2468d1..92794cd00b6 100644 --- a/homeassistant/components/tts/google.py +++ b/homeassistant/components/tts/google.py @@ -10,9 +10,10 @@ import re import aiohttp import async_timeout +import voluptuous as vol import yarl -from homeassistant.components.tts import Provider +from homeassistant.components.tts import Provider, PLATFORM_SCHEMA, CONF_LANG from homeassistant.helpers.aiohttp_client import async_get_clientsession REQUIREMENTS = ["gTTS-token==1.1.1"] @@ -22,6 +23,21 @@ _LOGGER = logging.getLogger(__name__) GOOGLE_SPEECH_URL = "http://translate.google.com/translate_tts" MESSAGE_SIZE = 148 +SUPPORT_LANGUAGES = [ + 'af', 'sq', 'ar', 'hy', 'bn', 'ca', 'zh', 'zh-cn', 'zh-tw', 'zh-yue', + 'hr', 'cs', 'da', 'nl', 'en', 'en-au', 'en-uk', 'en-us', 'eo', 'fi', + 'fr', 'de', 'el', 'hi', 'hu', 'is', 'id', 'it', 'ja', 'ko', 'la', 'lv', + 'mk', 'no', 'pl', 'pt', 'pt-br', 'ro', 'ru', 'sr', 'sk', 'es', 'es-es', + 'es-us', 'sw', 'sv', 'ta', 'th', 'tr', 'vi', 'cy', +] + +DEFAULT_LANG = 'en' + + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORT_LANGUAGES), +}) + @asyncio.coroutine def async_get_engine(hass, config): From 58ea3c25df9b9d8ee0b1d3197da529bb3015afa9 Mon Sep 17 00:00:00 2001 From: Daniel Hoyer Iversen Date: Thu, 15 Dec 2016 07:58:58 +0100 Subject: [PATCH 106/141] Update flux led lib --- homeassistant/components/light/flux_led.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/light/flux_led.py b/homeassistant/components/light/flux_led.py index 1e1d4136142..a5474612496 100644 --- a/homeassistant/components/light/flux_led.py +++ b/homeassistant/components/light/flux_led.py @@ -17,8 +17,8 @@ from homeassistant.components.light import ( PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['https://github.com/Danielhiversen/flux_led/archive/0.9.zip' - '#flux_led==0.9'] +REQUIREMENTS = ['https://github.com/Danielhiversen/flux_led/archive/0.10.zip' + '#flux_led==0.10'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 924f534145d..f56c576f366 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -173,7 +173,7 @@ hikvision==0.4 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 +https://github.com/Danielhiversen/flux_led/archive/0.10.zip#flux_led==0.10 # homeassistant.components.switch.tplink https://github.com/GadgetReactor/pyHS100/archive/1f771b7d8090a91c6a58931532e42730b021cbde.zip#pyHS100==0.2.0 From 1a7895b1d802aade6a3089f01022f38d861460bf Mon Sep 17 00:00:00 2001 From: Lewis Juggins Date: Thu, 15 Dec 2016 11:46:18 +0000 Subject: [PATCH 107/141] [media_player.sonos] Bugfix, initalise source_name. (#4911) --- 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 e9653d2a8d8..94649b3a597 100644 --- a/homeassistant/components/media_player/sonos.py +++ b/homeassistant/components/media_player/sonos.py @@ -427,6 +427,7 @@ class SonosDevice(MediaPlayerDevice): media_position = None media_position_updated_at = None + source_name = None is_radio_stream = \ current_media_uri.startswith('x-sonosapi-stream:') or \ From 43d18daebdbdf82133c8c1dbbae73bb50e894db8 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Thu, 15 Dec 2016 21:26:13 +0100 Subject: [PATCH 108/141] Homematic faster update with async (#4929) --- homeassistant/components/homematic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index 245e6a12cc2..00adf3701c0 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -825,7 +825,7 @@ class HMDevice(Entity): if have_change: _LOGGER.debug("%s update_ha_state after '%s'", self._name, attribute) - self.update_ha_state() + self.schedule_update_ha_state() def _subscribe_homematic_events(self): """Subscribe all required events to handle job.""" From 1d60760e21de6c0727458e5a4fafd2358e179b7a Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 16 Dec 2016 06:30:09 +0100 Subject: [PATCH 109/141] Protect add_job (#4932) --- homeassistant/core.py | 2 ++ tests/test_core.py | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/homeassistant/core.py b/homeassistant/core.py index 86cfec7099c..da4fd2ed102 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -184,6 +184,8 @@ class HomeAssistant(object): target: target to call. args: parameters for method to call. """ + if target is None: + raise ValueError("Don't call add_job with None.") self.loop.call_soon_threadsafe(self.async_add_job, target, *args) @callback diff --git a/tests/test_core.py b/tests/test_core.py index 9221ad68352..4049d10d32d 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6,6 +6,7 @@ from unittest.mock import patch, MagicMock from datetime import datetime, timedelta import pytz +import pytest import homeassistant.core as ha from homeassistant.exceptions import InvalidEntityFormatError @@ -214,6 +215,11 @@ class TestHomeAssistant(unittest.TestCase): assert len(self.hass._pending_tasks) == 0 assert len(call_count) == 2 + def test_add_job_with_none(self): + """Try to add a job with None as function.""" + with pytest.raises(ValueError): + self.hass.add_job(None, 'test_arg') + class TestEvent(unittest.TestCase): """A Test Event class.""" From 7bb0abdf09121b30e83b6337f5ac8f735ea9980f Mon Sep 17 00:00:00 2001 From: joopert Date: Fri, 16 Dec 2016 06:35:01 +0100 Subject: [PATCH 110/141] kodi fanart fix basic auth (#4930) --- homeassistant/components/media_player/kodi.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/homeassistant/components/media_player/kodi.py b/homeassistant/components/media_player/kodi.py index 68161deea2f..9676fe451c7 100644 --- a/homeassistant/components/media_player/kodi.py +++ b/homeassistant/components/media_player/kodi.py @@ -76,11 +76,17 @@ class KodiDevice(MediaPlayerDevice): import jsonrpc_requests self._name = name self._url = url + self._basic_auth_url = None kwargs = {'timeout': 5} if auth is not None: kwargs['auth'] = auth + scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url) + self._basic_auth_url = \ + urllib.parse.urlunsplit((scheme, '{}:{}@{}'.format + (auth[0], auth[1], netloc), + path, query, fragment)) self._server = jsonrpc_requests.Server( '{}/jsonrpc'.format(self._url), **kwargs) @@ -195,6 +201,11 @@ class KodiDevice(MediaPlayerDevice): url_components = urllib.parse.urlparse(self._item['thumbnail']) if url_components.scheme == 'image': + if self._basic_auth_url is not None: + return '{}/image/{}'.format( + self._basic_auth_url, + urllib.parse.quote_plus(self._item['thumbnail'])) + return '{}/image/{}'.format( self._url, urllib.parse.quote_plus(self._item['thumbnail'])) From ceac9eab94c7b9982296d74e956e8a7905815cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Fri, 16 Dec 2016 06:35:47 +0100 Subject: [PATCH 111/141] Bug fix for #4903 (#4927) --- homeassistant/components/sensor/systemmonitor.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/systemmonitor.py b/homeassistant/components/sensor/systemmonitor.py index 14eadb48984..b59c5d0cd43 100755 --- a/homeassistant/components/sensor/systemmonitor.py +++ b/homeassistant/components/sensor/systemmonitor.py @@ -27,14 +27,14 @@ SENSOR_TYPES = { 'memory_use': ['RAM Use', 'MiB', 'mdi:memory'], 'memory_free': ['RAM Free', 'MiB', 'mdi:memory'], 'processor_use': ['CPU Use', '%', 'mdi:memory'], - 'process': ['Process', '', 'mdi:memory'], + 'process': ['Process', ' ', 'mdi:memory'], 'swap_use_percent': ['Swap Use', '%', 'mdi:harddisk'], 'swap_use': ['Swap Use', 'GiB', 'mdi:harddisk'], 'swap_free': ['Swap Free', 'GiB', 'mdi:harddisk'], 'network_out': ['Sent', 'MiB', 'mdi:server-network'], 'network_in': ['Received', 'MiB', 'mdi:server-network'], - 'packets_out': ['Packets sent', '', 'mdi:server-network'], - 'packets_in': ['Packets received', '', 'mdi:server-network'], + 'packets_out': ['Packets sent', ' ', 'mdi:server-network'], + 'packets_in': ['Packets received', ' ', 'mdi:server-network'], 'ipv4_address': ['IPv4 address', '', 'mdi:server-network'], 'ipv6_address': ['IPv6 address', '', 'mdi:server-network'], 'last_boot': ['Last Boot', '', 'mdi:clock'], From f90b89bc746acb71772e60f287ff626873607802 Mon Sep 17 00:00:00 2001 From: Joe Rocklin Date: Fri, 16 Dec 2016 00:39:59 -0500 Subject: [PATCH 112/141] Add nest hvac state (#4810) * Add basic property details for Nest hvac_state * Add the hvac_state sensor * Update requirements and remove trailing whitespace Clean up the multiline docstring Adding a space between summary and description * Removing the hvac_state as a property on the nest climate * Update nest.py --- homeassistant/components/sensor/nest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/nest.py b/homeassistant/components/sensor/nest.py index b9dde96a98c..f7bbf41cff9 100644 --- a/homeassistant/components/sensor/nest.py +++ b/homeassistant/components/sensor/nest.py @@ -18,7 +18,8 @@ from homeassistant.const import ( DEPENDENCIES = ['nest'] SENSOR_TYPES = ['humidity', - 'operation_mode'] + 'operation_mode', + 'hvac_state'] SENSOR_TYPES_DEPRECATED = ['last_ip', 'local_ip', From c125c4af4f4044d6bae4d0ca9c79125747a1db28 Mon Sep 17 00:00:00 2001 From: Hugo Dupras Date: Fri, 16 Dec 2016 06:40:33 +0100 Subject: [PATCH 113/141] Fix for GTFS sensor (#4828) * Fix for GTFS sensor Signed-off-by: Hugo D. (jabesq) * GTFS fix Signed-off-by: Hugo D. (jabesq) --- homeassistant/components/sensor/gtfs.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/homeassistant/components/sensor/gtfs.py b/homeassistant/components/sensor/gtfs.py index e76b8ed07ed..5769860284c 100644 --- a/homeassistant/components/sensor/gtfs.py +++ b/homeassistant/components/sensor/gtfs.py @@ -95,6 +95,9 @@ def get_next_departure(sched, start_station_id, end_station_id): for row in result: item = row + if item == {}: + return None + today = datetime.datetime.today().strftime('%Y-%m-%d') departure_time_string = '{} {}'.format(today, item[2]) arrival_time_string = '{} {}'.format(today, item[3]) @@ -221,6 +224,13 @@ class GTFSDepartureSensor(Entity): with self.lock: self._departure = get_next_departure(self._pygtfs, self.origin, self.destination) + if not self._departure: + self._state = 0 + self._attributes = {'Info': 'No more bus today'} + if self._name == '': + self._name = (self._custom_name or "GTFS Sensor") + return + self._state = self._departure['minutes_until_departure'] origin_station = self._departure['origin_station'] From 394d53e748f3bea40990074fcc516de2695aa25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Fri, 16 Dec 2016 06:42:00 +0100 Subject: [PATCH 114/141] Broadlink sensor and switch (#4834) * Broadlink sensor and switch * broadlink logging * Use async * style * style --- .coveragerc | 2 + homeassistant/components/sensor/broadlink.py | 130 +++++++++++++++ homeassistant/components/switch/broadlink.py | 158 +++++++++++++++++++ requirements_all.txt | 4 + 4 files changed, 294 insertions(+) create mode 100644 homeassistant/components/sensor/broadlink.py create mode 100644 homeassistant/components/switch/broadlink.py diff --git a/.coveragerc b/.coveragerc index 3168a20bd8c..d929d50271b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -252,6 +252,7 @@ omit = homeassistant/components/sensor/bbox.py homeassistant/components/sensor/bitcoin.py homeassistant/components/sensor/bom.py + homeassistant/components/sensor/broadlink.py homeassistant/components/sensor/coinmarketcap.py homeassistant/components/sensor/cpuspeed.py homeassistant/components/sensor/cups.py @@ -323,6 +324,7 @@ omit = homeassistant/components/switch/acer_projector.py homeassistant/components/switch/anel_pwrctrl.py homeassistant/components/switch/arest.py + homeassistant/components/switch/broadlink.py homeassistant/components/switch/digitalloggers.py homeassistant/components/switch/dlink.py homeassistant/components/switch/edimax.py diff --git a/homeassistant/components/sensor/broadlink.py b/homeassistant/components/sensor/broadlink.py new file mode 100644 index 00000000000..53aac3d353a --- /dev/null +++ b/homeassistant/components/sensor/broadlink.py @@ -0,0 +1,130 @@ + +""" +Support for the Broadlink RM2 Pro (only temperature) and A1 devices. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.broadlink/ +""" +from datetime import timedelta +import binascii +import logging +import socket +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import (CONF_HOST, CONF_MAC, + CONF_MONITORED_CONDITIONS, + CONF_NAME, TEMP_CELSIUS, CONF_TIMEOUT) +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['broadlink==0.2'] + +_LOGGER = logging.getLogger(__name__) + +CONF_UPDATE_INTERVAL = 'update_interval' +DEVICE_DEFAULT_NAME = 'Broadlink sensor' +DEFAULT_TIMEOUT = 10 + +SENSOR_TYPES = { + 'temperature': ['Temperature', TEMP_CELSIUS], + 'air_quality': ['Air Quality', ' '], + 'humidity': ['Humidity', '%'], + 'light': ['Light', ' '], + 'noise': ['Noise', ' '] +} + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=DEVICE_DEFAULT_NAME): vol.Coerce(str), + vol.Optional(CONF_MONITORED_CONDITIONS, default=[]): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), + vol.Optional(CONF_UPDATE_INTERVAL, default=timedelta(seconds=300)): ( + vol.All(cv.time_period, cv.positive_timedelta)), + vol.Required(CONF_HOST): cv.string, + vol.Required(CONF_MAC): cv.string, + vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int +}) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Broadlink device sensors.""" + mac = config.get(CONF_MAC).encode().replace(b':', b'') + mac_addr = binascii.unhexlify(mac) + broadlink_data = BroadlinkData( + config.get(CONF_UPDATE_INTERVAL), + config.get(CONF_HOST), + mac_addr, config.get(CONF_TIMEOUT)) + + dev = [] + for variable in config[CONF_MONITORED_CONDITIONS]: + dev.append(BroadlinkSensor( + config.get(CONF_NAME), + broadlink_data, + variable)) + add_devices(dev) + + +class BroadlinkSensor(Entity): + """Representation of a Broadlink device sensor.""" + + def __init__(self, name, broadlink_data, sensor_type): + """Initialize the sensor.""" + self._name = "%s %s" % (name, SENSOR_TYPES[sensor_type][0]) + self._state = None + self._type = sensor_type + self._broadlink_data = broadlink_data + self._unit_of_measurement = SENSOR_TYPES[sensor_type][1] + self.update() + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def unit_of_measurement(self): + """Return the unit this state is expressed in.""" + return self._unit_of_measurement + + def update(self): + """Get the latest data from the sensor.""" + self._broadlink_data.update() + if self._broadlink_data.data is None: + return + self._state = self._broadlink_data.data[self._type] + + +class BroadlinkData(object): + """Representation of a Broadlink data object.""" + + def __init__(self, interval, ip_addr, mac_addr, timeout): + """Initialize the data object.""" + import broadlink + self.data = None + self._device = broadlink.a1((ip_addr, 80), mac_addr) + self._device.timeout = timeout + self.update = Throttle(interval)(self._update) + try: + self._device.auth() + except socket.timeout: + _LOGGER.error("Failed to connect to device.") + + def _update(self, retry=2): + try: + self.data = self._device.check_sensors_raw() + except socket.timeout as error: + if retry < 1: + _LOGGER.error(error) + return + try: + self._device.auth() + except socket.timeout: + pass + return self._update(max(0, retry-1)) diff --git a/homeassistant/components/switch/broadlink.py b/homeassistant/components/switch/broadlink.py new file mode 100644 index 00000000000..ee71de3a22e --- /dev/null +++ b/homeassistant/components/switch/broadlink.py @@ -0,0 +1,158 @@ +""" +Support for Broadlink RM devices. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/switch.broadlink/ +""" +from datetime import timedelta +from base64 import b64encode, b64decode +import asyncio +import binascii +import logging +import socket +import voluptuous as vol + +import homeassistant.loader as loader +from homeassistant.util.dt import utcnow +from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) +from homeassistant.const import (CONF_FRIENDLY_NAME, CONF_SWITCHES, + CONF_COMMAND_OFF, CONF_COMMAND_ON, + CONF_TIMEOUT, CONF_HOST, CONF_MAC) +import homeassistant.helpers.config_validation as cv + +REQUIREMENTS = ['broadlink==0.2'] + +_LOGGER = logging.getLogger(__name__) + +DOMAIN = "broadlink" +DEFAULT_NAME = 'Broadlink switch' +DEFAULT_TIMEOUT = 10 +SERVICE_LEARN = "learn_command" + +SWITCH_SCHEMA = vol.Schema({ + vol.Optional(CONF_COMMAND_OFF, default=None): cv.string, + vol.Optional(CONF_COMMAND_ON, default=None): cv.string, + vol.Optional(CONF_FRIENDLY_NAME, default=DEFAULT_NAME): cv.string, +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_SWITCHES): vol.Schema({cv.slug: SWITCH_SCHEMA}), + vol.Required(CONF_HOST): cv.string, + vol.Required(CONF_MAC): cv.string, + vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup Broadlink switches.""" + import broadlink + devices = config.get(CONF_SWITCHES, {}) + switches = [] + ip_addr = config.get(CONF_HOST) + mac_addr = binascii.unhexlify( + config.get(CONF_MAC).encode().replace(b':', b'')) + broadlink_device = broadlink.rm((ip_addr, 80), mac_addr) + broadlink_device.timeout = config.get(CONF_TIMEOUT) + try: + broadlink_device.auth() + except socket.timeout: + _LOGGER.error("Failed to connect to device.") + + persistent_notification = loader.get_component('persistent_notification') + + @asyncio.coroutine + def _learn_command(call): + try: + yield from hass.loop.run_in_executor(None, broadlink_device.auth) + except socket.timeout: + _LOGGER.error("Failed to connect to device.") + return + yield from hass.loop.run_in_executor(None, + broadlink_device.enter_learning) + + _LOGGER.info("Press the key you want HASS to learn") + start_time = utcnow() + while (utcnow() - start_time) < timedelta(seconds=20): + packet = yield from hass.loop.run_in_executor(None, + broadlink_device. + check_data) + if packet: + log_msg = 'Recieved packet is: {}'.\ + format(b64encode(packet).decode('utf8')) + _LOGGER.info(log_msg) + persistent_notification.async_create(hass, log_msg, + title='Broadlink switch') + return + yield from asyncio.sleep(1, loop=hass.loop) + _LOGGER.error('Did not received any signal.') + persistent_notification.async_create(hass, + "Did not received any signal", + title='Broadlink switch') + hass.services.register(DOMAIN, SERVICE_LEARN, _learn_command) + + for object_id, device_config in devices.items(): + switches.append( + BroadlinkRM2Switch( + device_config.get(CONF_FRIENDLY_NAME, object_id), + device_config.get(CONF_COMMAND_ON), + device_config.get(CONF_COMMAND_OFF), + broadlink_device + ) + ) + + add_devices(switches) + + +class BroadlinkRM2Switch(SwitchDevice): + """Representation of an Broadlink switch.""" + + def __init__(self, friendly_name, command_on, command_off, device): + """Initialize the switch.""" + self._name = friendly_name + self._state = False + self._command_on = b64decode(command_on) if command_on else None + self._command_off = b64decode(command_off) if command_off else None + self._device = device + + @property + def name(self): + """Return the name of the switch.""" + return self._name + + @property + def assumed_state(self): + """Return true if unable to access real state of entity.""" + return True + + @property + def is_on(self): + """Return true if device is on.""" + return self._state + + def turn_on(self, **kwargs): + """Turn the device on.""" + if self._sendpacket(self._command_on): + self._state = True + + def turn_off(self, **kwargs): + """Turn the device off.""" + if self._sendpacket(self._command_off): + self._state = False + + def _sendpacket(self, packet, retry=2): + """Send packet to device.""" + if packet is None: + _LOGGER.debug("Empty packet.") + return True + try: + self._device.send_data(packet) + except socket.timeout as error: + if retry < 1: + _LOGGER.error(error) + return False + try: + self._device.auth() + except socket.timeout: + pass + return self._sendpacket(packet, max(0, retry-1)) + return True diff --git a/requirements_all.txt b/requirements_all.txt index f56c576f366..81b6eef84a4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -65,6 +65,10 @@ blockchain==1.3.3 # homeassistant.components.notify.aws_sqs boto3==1.3.1 +# homeassistant.components.sensor.broadlink +# homeassistant.components.switch.broadlink +broadlink==0.2 + # homeassistant.components.sensor.coinmarketcap coinmarketcap==2.0.1 From 7b45cf8e59bf7c40cf3b18c446c912b9874e0dbd Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Thu, 15 Dec 2016 23:47:23 -0600 Subject: [PATCH 115/141] Expose media volume as emulated Hue brightness (#4869) * Allow virtual Hue bridge to set volume level of media_player entities * Show correct states in all lights view --- .../components/emulated_hue/hue_api.py | 111 ++++++++++++------ tests/components/emulated_hue/test_hue_api.py | 63 +++++++++- 2 files changed, 136 insertions(+), 38 deletions(-) diff --git a/homeassistant/components/emulated_hue/hue_api.py b/homeassistant/components/emulated_hue/hue_api.py index 32fb4af071c..57a4f18825a 100644 --- a/homeassistant/components/emulated_hue/hue_api.py +++ b/homeassistant/components/emulated_hue/hue_api.py @@ -6,12 +6,16 @@ from aiohttp import web from homeassistant import core from homeassistant.const import ( - ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_ON, - STATE_OFF, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, + ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_VOLUME_SET, + STATE_ON, STATE_OFF, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, ) from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_SUPPORTED_FEATURES, SUPPORT_BRIGHTNESS ) +from homeassistant.components.media_player import ( + ATTR_MEDIA_VOLUME_LEVEL, ATTR_SUPPORTED_MEDIA_COMMANDS, + SUPPORT_VOLUME_SET, +) from homeassistant.components.http import HomeAssistantView _LOGGER = logging.getLogger(__name__) @@ -65,8 +69,11 @@ class HueAllLightsStateView(HomeAssistantView): for entity in hass.states.async_all(): if self.config.is_entity_exposed(entity): + state, brightness = get_entity_state(self.config, entity) + number = self.config.entity_id_to_number(entity.entity_id) - json_response[number] = entity_to_json(entity) + json_response[number] = entity_to_json( + entity, state, brightness) return self.json(json_response) @@ -97,16 +104,9 @@ class HueOneLightStateView(HomeAssistantView): _LOGGER.error('Entity not exposed: %s', entity_id) return web.Response(text="Entity not exposed", status=404) - cached_state = self.config.cached_states.get(entity_id, None) + state, brightness = get_entity_state(self.config, entity) - if cached_state is None: - final_state = entity.state == STATE_ON - final_brightness = entity.attributes.get( - ATTR_BRIGHTNESS, 255 if final_state else 0) - else: - final_state, final_brightness = cached_state - - json_response = entity_to_json(entity, final_state, final_brightness) + json_response = entity_to_json(entity, state, brightness) return self.json(json_response) @@ -158,14 +158,24 @@ class HueOneLightChangeView(HomeAssistantView): result, brightness = parsed + # Choose general HA domain + domain = core.DOMAIN + # Convert the resulting "on" status into the service we need to call service = SERVICE_TURN_ON if result else SERVICE_TURN_OFF # Construct what we need to send to the service data = {ATTR_ENTITY_ID: entity_id} + # Make sure the entity actually supports brightness + entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) + + if (entity_features & SUPPORT_BRIGHTNESS) == SUPPORT_BRIGHTNESS: + if brightness is not None: + data[ATTR_BRIGHTNESS] = brightness + # If the requested entity is a script add some variables - if entity.domain == "script": + elif entity.domain == "script": data['variables'] = { 'requested_state': STATE_ON if result else STATE_OFF } @@ -173,8 +183,16 @@ class HueOneLightChangeView(HomeAssistantView): if brightness is not None: data['variables']['requested_level'] = brightness - elif brightness is not None: - data[ATTR_BRIGHTNESS] = brightness + # If the requested entity is a media player, convert to volume + elif entity.domain == "media_player": + media_commands = entity.attributes.get( + ATTR_SUPPORTED_MEDIA_COMMANDS, 0) + if media_commands & SUPPORT_VOLUME_SET == SUPPORT_VOLUME_SET: + if brightness is not None: + domain = entity.domain + service = SERVICE_VOLUME_SET + # Convert 0-100 to 0.0-1.0 + data[ATTR_MEDIA_VOLUME_LEVEL] = brightness / 100.0 if entity.domain in config.off_maps_to_on_domains: # Map the off command to on @@ -187,9 +205,14 @@ class HueOneLightChangeView(HomeAssistantView): # as the actual requested command. config.cached_states[entity_id] = (result, brightness) - # Perform the requested action - yield from hass.services.async_call(core.DOMAIN, service, data, - blocking=True) + # Separate call to turn on needed + if domain != core.DOMAIN: + hass.async_add_job(hass.services.async_call( + core.DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, + blocking=True)) + + hass.async_add_job(hass.services.async_call( + domain, service, data, blocking=True)) json_response = \ [create_hue_success_response(entity_id, HUE_API_STATE_ON, result)] @@ -219,23 +242,23 @@ def parse_hue_api_put_light_body(request_json, entity): result = False if HUE_API_STATE_BRI in request_json: + try: + # Clamp brightness from 0 to 255 + brightness = \ + max(0, min(int(request_json[HUE_API_STATE_BRI]), 255)) + except ValueError: + return None + # Make sure the entity actually supports brightness entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) if (entity_features & SUPPORT_BRIGHTNESS) == SUPPORT_BRIGHTNESS: - try: - # Clamp brightness from 0 to 255 - brightness = \ - max(0, min(int(request_json[HUE_API_STATE_BRI]), 255)) - except ValueError: - return None - report_brightness = True result = (brightness > 0) - elif entity.domain.lower() == "script": - # Convert 0-255 to 0-100 - level = int(request_json[HUE_API_STATE_BRI]) / 255 * 100 + elif entity.domain == "script" or entity.domain == "media_player": + # Convert 0-255 to 0-100 + level = brightness / 255 * 100 brightness = round(level) report_brightness = True result = True @@ -243,14 +266,34 @@ def parse_hue_api_put_light_body(request_json, entity): return (result, brightness) if report_brightness else (result, None) +def get_entity_state(config, entity): + """Retrieve and convert state and brightness values for an entity.""" + cached_state = config.cached_states.get(entity.entity_id, None) + + if cached_state is None: + final_state = entity.state != STATE_OFF + final_brightness = entity.attributes.get( + ATTR_BRIGHTNESS, 255 if final_state else 0) + + # Make sure the entity actually supports brightness + entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) + + if (entity_features & SUPPORT_BRIGHTNESS) == SUPPORT_BRIGHTNESS: + pass + + elif entity.domain == "media_player": + level = entity.attributes.get( + ATTR_MEDIA_VOLUME_LEVEL, 1.0 if final_state else 0.0) + # Convert 0.0-1.0 to 0-255 + final_brightness = round(min(1.0, level) * 255) + else: + final_state, final_brightness = cached_state + + return (final_state, final_brightness) + + def entity_to_json(entity, is_on=None, brightness=None): """Convert an entity to its Hue bridge JSON representation.""" - if is_on is None: - is_on = entity.state == STATE_ON - - if brightness is None: - brightness = 255 if is_on else 0 - name = entity.attributes.get(ATTR_EMULATED_HUE_NAME, entity.name) return { diff --git a/tests/components/emulated_hue/test_hue_api.py b/tests/components/emulated_hue/test_hue_api.py index 9cee27f570f..4aab6401939 100644 --- a/tests/components/emulated_hue/test_hue_api.py +++ b/tests/components/emulated_hue/test_hue_api.py @@ -7,7 +7,9 @@ import requests from homeassistant import bootstrap, const, core import homeassistant.components as core_components -from homeassistant.components import emulated_hue, http, light, script +from homeassistant.components import ( + emulated_hue, http, light, script, media_player +) from homeassistant.const import STATE_ON, STATE_OFF from homeassistant.components.emulated_hue.hue_api import ( HUE_API_STATE_ON, HUE_API_STATE_BRI) @@ -73,6 +75,14 @@ class TestEmulatedHueExposedByDefault(unittest.TestCase): } }) + bootstrap.setup_component(cls.hass, media_player.DOMAIN, { + 'media_player': [ + { + 'platform': 'demo', + } + ] + }) + cls.hass.start() # Kitchen light is explicitly excluded from being exposed @@ -111,6 +121,10 @@ class TestEmulatedHueExposedByDefault(unittest.TestCase): self.assertTrue('light.bed_light' in result_json) self.assertTrue('script.set_kitchen_light' in result_json) self.assertTrue('light.kitchen_lights' not in result_json) + self.assertTrue('media_player.living_room' in result_json) + self.assertTrue('media_player.bedroom' in result_json) + self.assertTrue('media_player.walkman' in result_json) + self.assertTrue('media_player.lounge_room' in result_json) def test_get_light_state(self): """Test the getting of light state.""" @@ -128,6 +142,21 @@ class TestEmulatedHueExposedByDefault(unittest.TestCase): self.assertEqual(office_json['state'][HUE_API_STATE_ON], True) self.assertEqual(office_json['state'][HUE_API_STATE_BRI], 127) + # Check all lights view + result = requests.get( + BRIDGE_URL_BASE.format('/api/username/lights'), timeout=5) + + self.assertEqual(result.status_code, 200) + self.assertTrue('application/json' in result.headers['content-type']) + + result_json = result.json() + + self.assertTrue('light.ceiling_lights' in result_json) + self.assertEqual( + result_json['light.ceiling_lights']['state'][HUE_API_STATE_BRI], + 127, + ) + # Turn bedroom light off self.hass.services.call( light.DOMAIN, const.SERVICE_TURN_OFF, @@ -204,15 +233,38 @@ class TestEmulatedHueExposedByDefault(unittest.TestCase): self.assertEqual(script_result.status_code, 200) self.assertEqual(len(script_result_json), 2) - # Wait until script is complete before continuing - self.hass.block_till_done() - kitchen_light = self.hass.states.get('light.kitchen_lights') self.assertEqual(kitchen_light.state, 'on') self.assertEqual( kitchen_light.attributes[light.ATTR_BRIGHTNESS], level) + def test_put_light_state_media_player(self): + """Test turning on media player and setting volume.""" + # Turn the music player off first + self.hass.services.call( + media_player.DOMAIN, const.SERVICE_TURN_OFF, + {const.ATTR_ENTITY_ID: 'media_player.walkman'}, + blocking=True) + + # Emulated hue converts 0.0-1.0 to 0-255. + level = 0.25 + brightness = round(level * 255) + + mp_result = self.perform_put_light_state( + 'media_player.walkman', True, brightness) + + mp_result_json = mp_result.json() + + self.assertEqual(mp_result.status_code, 200) + self.assertEqual(len(mp_result_json), 2) + + walkman = self.hass.states.get('media_player.walkman') + self.assertEqual(walkman.state, 'playing') + self.assertEqual( + walkman.attributes[media_player.ATTR_MEDIA_VOLUME_LEVEL], + level) + # pylint: disable=invalid-name def test_put_with_form_urlencoded_content_type(self): """Test the form with urlencoded content.""" @@ -352,4 +404,7 @@ class TestEmulatedHueExposedByDefault(unittest.TestCase): result = requests.put( url, data=json.dumps(data), timeout=5, headers=req_headers) + # Wait until state change is complete before continuing + self.hass.block_till_done() + return result From 5b70ada7b4d352d998d1d35fd604943499becf0d Mon Sep 17 00:00:00 2001 From: Magas Date: Fri, 16 Dec 2016 01:11:58 -0500 Subject: [PATCH 116/141] Panasonic viera fix (#4888) * Removed return False so the Panasonic Viera TV can be added even if it doesn't connect * Removed return False so the Panasonic Viera TV can be added even if it doesn't connect * Removed return False so the Panasonic Viera TV can be added even if it doesn't connect * Remove try/except to connect to the TV * Update panasonic_viera.py * Update panasonic_viera.py --- homeassistant/components/media_player/panasonic_viera.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/homeassistant/components/media_player/panasonic_viera.py b/homeassistant/components/media_player/panasonic_viera.py index 987364bbf63..bbac8f243d3 100644 --- a/homeassistant/components/media_player/panasonic_viera.py +++ b/homeassistant/components/media_player/panasonic_viera.py @@ -57,13 +57,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): host = config.get(CONF_HOST) remote = RemoteControl(host, port) - try: - remote.get_mute() - except OSError as error: - _LOGGER.error('Panasonic Viera TV is not available at %s:%d: %s', - host, port, error) - return False - add_devices([PanasonicVieraTVDevice(name, remote)]) return True From 2a31bb48c6907731ca729101fc687c98344a8ecc Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 16 Dec 2016 07:12:33 +0100 Subject: [PATCH 117/141] Clean-up (#4894) --- homeassistant/components/sensor/arwn.py | 42 +++++++++++++------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/sensor/arwn.py b/homeassistant/components/sensor/arwn.py index 5eb95ba16d1..c0012b4ac92 100644 --- a/homeassistant/components/sensor/arwn.py +++ b/homeassistant/components/sensor/arwn.py @@ -1,23 +1,25 @@ -"""Support for collecting data from the ARWN project. - -For more details about this platform, please refer to the -documentation at https://home-assistant.io/components/sensor.arwn/ +""" +Support for collecting data from the ARWN project. +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.arwn/ """ import json import logging -from homeassistant.helpers.entity import Entity + import homeassistant.components.mqtt as mqtt from homeassistant.const import (TEMP_FAHRENHEIT, TEMP_CELSIUS) +from homeassistant.helpers.entity import Entity from homeassistant.util import slugify -DEPENDENCIES = ['mqtt'] +_LOGGER = logging.getLogger(__name__) + +DEPENDENCIES = ['mqtt'] +DOMAIN = 'arwn' -DOMAIN = "arwn" -TOPIC = 'arwn/#' SENSORS = {} -_LOGGER = logging.getLogger(__name__) +TOPIC = 'arwn/#' def discover_sensors(topic, payload): @@ -25,23 +27,23 @@ def discover_sensors(topic, payload): parts = topic.split('/') unit = payload.get('units', '') domain = parts[1] - if domain == "temperature": + if domain == 'temperature': name = parts[2] - if unit == "F": + if unit == 'F': unit = TEMP_FAHRENHEIT else: unit = TEMP_CELSIUS - return (ArwnSensor(name, 'temp', unit),) - if domain == "barometer": - return (ArwnSensor("Barometer", 'pressure', unit),) - if domain == "wind": - return (ArwnSensor("Wind Speed", 'speed', unit), - ArwnSensor("Wind Gust", 'gust', unit), - ArwnSensor("Wind Direction", 'direction', '°')) + return ArwnSensor(name, 'temp', unit) + if domain == 'barometer': + return ArwnSensor('Barometer', 'pressure', unit) + if domain == 'wind': + return (ArwnSensor('Wind Speed', 'speed', unit), + ArwnSensor('Wind Gust', 'gust', unit), + ArwnSensor('Wind Direction', 'direction', '°')) def _slug(name): - return "sensor.arwn_%s" % slugify(name) + return 'sensor.arwn_{}'.format(slugify(name)) def setup_platform(hass, config, add_devices, discovery_info=None): @@ -84,7 +86,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class ArwnSensor(Entity): - """Represents an ARWN sensor.""" + """Representation of an ARWN sensor.""" def __init__(self, name, state_key, units): """Initialize the sensor.""" From 02517ae5ec148d021cbeaed9bab86fef5e2e7a2a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 15 Dec 2016 22:13:38 -0800 Subject: [PATCH 118/141] Fix synologydsm (#4895) --- homeassistant/components/sensor/synologydsm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/synologydsm.py b/homeassistant/components/sensor/synologydsm.py index 6dc23a71d9b..8ee0d6eae18 100644 --- a/homeassistant/components/sensor/synologydsm.py +++ b/homeassistant/components/sensor/synologydsm.py @@ -107,7 +107,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): # Handle all Volumes volumes = config['volumes'] if volumes is None: - volumes = api.storage().volumes + volumes = api.storage.volumes for volume in volumes: sensors += [SynoNasStorageSensor(api, variable, @@ -119,7 +119,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): # Handle all Disks disks = config['disks'] if disks is None: - disks = api.storage().disks + disks = api.storage.disks for disk in disks: sensors += [SynoNasStorageSensor(api, variable, From 7748867732b4314db6d84d3ffeca4c0cf93b2f23 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Fri, 16 Dec 2016 07:14:59 +0100 Subject: [PATCH 119/141] Avoid TypeError for state (#4897) --- homeassistant/components/sensor/coinmarketcap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/coinmarketcap.py b/homeassistant/components/sensor/coinmarketcap.py index e041352af58..eee43328f29 100644 --- a/homeassistant/components/sensor/coinmarketcap.py +++ b/homeassistant/components/sensor/coinmarketcap.py @@ -77,7 +77,7 @@ class CoinMarketCapSensor(Entity): @property def state(self): """Return the state of the sensor.""" - return round(self._ticker.get('price_usd'), 2) + return round(float(self._ticker.get('price_usd')), 2) @property def unit_of_measurement(self): From 103fffa0f4498a09b32c3f9547dcb974978b7729 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Fri, 16 Dec 2016 07:20:00 +0100 Subject: [PATCH 120/141] Add support for new netdisco detection of Samsung Smart TV. (#4925) --- homeassistant/components/discovery.py | 1 + .../components/media_player/samsungtv.py | 54 ++++++++++++++----- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py index 74dc5d69220..32cb205fa0f 100644 --- a/homeassistant/components/discovery.py +++ b/homeassistant/components/discovery.py @@ -37,6 +37,7 @@ SERVICE_HANDLERS = { 'logitech_mediaserver': ('media_player', 'squeezebox'), 'directv': ('media_player', 'directv'), 'denonavr': ('media_player', 'denonavr'), + 'samsung_tv': ('media_player', 'samsungtv'), } CONFIG_SCHEMA = vol.Schema({ diff --git a/homeassistant/components/media_player/samsungtv.py b/homeassistant/components/media_player/samsungtv.py index a43e8b551a3..c7705393381 100644 --- a/homeassistant/components/media_player/samsungtv.py +++ b/homeassistant/components/media_player/samsungtv.py @@ -5,6 +5,7 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/media_player.samsungtv/ """ import logging +import socket import voluptuous as vol @@ -26,6 +27,8 @@ DEFAULT_NAME = 'Samsung TV Remote' DEFAULT_PORT = 55000 DEFAULT_TIMEOUT = 0 +KNOWN_DEVICES_KEY = 'samsungtv_known_devices' + SUPPORT_SAMSUNGTV = SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | \ SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | \ SUPPORT_NEXT_TRACK | SUPPORT_TURN_OFF @@ -41,25 +44,42 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Samsung TV platform.""" - name = config.get(CONF_NAME) + known_devices = hass.data.get(KNOWN_DEVICES_KEY) + if known_devices is None: + known_devices = set() + hass.data[KNOWN_DEVICES_KEY] = known_devices - # Generate a configuration for the Samsung library - remote_config = { - 'name': 'HomeAssistant', - 'description': config.get(CONF_NAME), - 'id': 'ha.component.samsung', - 'port': config.get(CONF_PORT), - 'host': config.get(CONF_HOST), - 'timeout': config.get(CONF_TIMEOUT), - } + # Is this a manual configuration? + if config.get(CONF_HOST) is not None: + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + name = config.get(CONF_NAME) + timeout = config.get(CONF_TIMEOUT) + elif discovery_info is not None: + tv_name, model, host = discovery_info + name = "{} ({})".format(tv_name, model) + port = DEFAULT_PORT + timeout = DEFAULT_TIMEOUT + else: + _LOGGER.warning( + 'Internal error on samsungtv component. Cannot determine device') + return - add_devices([SamsungTVDevice(name, remote_config)]) + # Only add a device once, so discovered devices do not override manual + # config. + ip_addr = socket.gethostbyname(host) + if ip_addr not in known_devices: + known_devices.add(ip_addr) + add_devices([SamsungTVDevice(host, port, name, timeout)]) + _LOGGER.info("Samsung TV %s:%d added as '%s'", host, port, name) + else: + _LOGGER.info("Ignoring duplicate Samsung TV %s:%d", host, port) class SamsungTVDevice(MediaPlayerDevice): """Representation of a Samsung TV.""" - def __init__(self, name, config): + def __init__(self, host, port, name, timeout): """Initialize the Samsung device.""" from samsungctl import Remote # Save a reference to the imported class @@ -71,7 +91,15 @@ class SamsungTVDevice(MediaPlayerDevice): self._playing = True self._state = STATE_UNKNOWN self._remote = None - self._config = config + # Generate a configuration for the Samsung library + self._config = { + 'name': 'HomeAssistant', + 'description': name, + 'id': 'ha.component.samsung', + 'port': port, + 'host': host, + 'timeout': timeout, + } def update(self): """Retrieve the latest data.""" From b9dcc2777b0cff2f874ad7de1b846958070e4777 Mon Sep 17 00:00:00 2001 From: Adam Mills Date: Fri, 16 Dec 2016 01:27:37 -0500 Subject: [PATCH 121/141] Setup DarkSky platform when offline during init (#4919) * Setup DarkSky platform when offline during init * Fail setup_platform if fetch was unsuccessful --- homeassistant/components/sensor/darksky.py | 42 +++++++++++----------- tests/components/sensor/test_darksky.py | 13 ++++++- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/homeassistant/components/sensor/darksky.py b/homeassistant/components/sensor/darksky.py index c57b4ba30e8..173990a6a2f 100644 --- a/homeassistant/components/sensor/darksky.py +++ b/homeassistant/components/sensor/darksky.py @@ -104,19 +104,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None): else: units = 'us' - # Create a data fetcher to support all of the configured sensors. Then make - # the first call to init the data and confirm we can connect. - try: - forecast_data = DarkSkyData( - api_key=config.get(CONF_API_KEY, None), - latitude=hass.config.latitude, - longitude=hass.config.longitude, - units=units, - interval=config.get(CONF_UPDATE_INTERVAL)) - forecast_data.update() - forecast_data.update_currently() - except ValueError as error: - _LOGGER.error(error) + forecast_data = DarkSkyData( + api_key=config.get(CONF_API_KEY, None), + latitude=hass.config.latitude, + longitude=hass.config.longitude, + units=units, + interval=config.get(CONF_UPDATE_INTERVAL)) + forecast_data.update() + forecast_data.update_currently() + + # If connection failed don't setup platform. + if forecast_data.data is None: return False name = config.get(CONF_NAME) @@ -227,7 +225,10 @@ class DarkSkySensor(Entity): If the sensor type is unknown, the current state is returned. """ lookup_type = convert_to_camel(self.type) - state = getattr(data, lookup_type, 0) + state = getattr(data, lookup_type, None) + + if state is None: + return state # Some state data needs to be rounded to whole values or converted to # percentages @@ -284,21 +285,22 @@ class DarkSkyData(object): self.data = forecastio.load_forecast( self._api_key, self.latitude, self.longitude, units=self.units) except (ConnectError, HTTPError, Timeout, ValueError) as error: - raise ValueError("Unable to init Dark Sky. %s", error) - self.unit_system = self.data.json['flags']['units'] + _LOGGER.error("Unable to connect to Dark Sky. %s", error) + self.data = None + self.unit_system = self.data and self.data.json['flags']['units'] def _update_currently(self): """Update currently data.""" - self.data_currently = self.data.currently() + self.data_currently = self.data and self.data.currently() def _update_minutely(self): """Update minutely data.""" - self.data_minutely = self.data.minutely() + self.data_minutely = self.data and self.data.minutely() def _update_hourly(self): """Update hourly data.""" - self.data_hourly = self.data.hourly() + self.data_hourly = self.data and self.data.hourly() def _update_daily(self): """Update daily data.""" - self.data_daily = self.data.daily() + self.data_daily = self.data and self.data.daily() diff --git a/tests/components/sensor/test_darksky.py b/tests/components/sensor/test_darksky.py index 09ced049b58..976a9278452 100644 --- a/tests/components/sensor/test_darksky.py +++ b/tests/components/sensor/test_darksky.py @@ -17,6 +17,15 @@ from tests.common import load_fixture, get_test_home_assistant class TestDarkSkySetup(unittest.TestCase): """Test the Dark Sky platform.""" + def add_entities(self, new_entities, update_before_add=False): + """Mock add entities.""" + if update_before_add: + for entity in new_entities: + entity.update() + + for entity in new_entities: + self.entities.append(entity) + def setUp(self): """Initialize values for this testcase class.""" self.hass = get_test_home_assistant() @@ -30,6 +39,7 @@ class TestDarkSkySetup(unittest.TestCase): self.lon = -122.423 self.hass.config.latitude = self.lat self.hass.config.longitude = self.lon + self.entities = [] def test_setup_with_config(self): """Test the platform setup with configuration.""" @@ -63,6 +73,7 @@ class TestDarkSkySetup(unittest.TestCase): r'(-?\d+\.?\d*),(-?\d+\.?\d*)') mock_req.get(re.compile(uri), text=load_fixture('darksky.json')) - darksky.setup_platform(self.hass, self.config, MagicMock()) + darksky.setup_platform(self.hass, self.config, self.add_entities) self.assertTrue(mock_get_forecast.called) self.assertEqual(mock_get_forecast.call_count, 1) + self.assertEqual(len(self.entities), 2) From 757f6278eb93db41d0a57137969635c24afc3304 Mon Sep 17 00:00:00 2001 From: Erik Eriksson Date: Fri, 16 Dec 2016 07:35:53 +0100 Subject: [PATCH 122/141] initialize self._last_brightness (#4917) --- homeassistant/components/light/tellduslive.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/light/tellduslive.py b/homeassistant/components/light/tellduslive.py index f919268c380..31f9eb1d253 100644 --- a/homeassistant/components/light/tellduslive.py +++ b/homeassistant/components/light/tellduslive.py @@ -26,9 +26,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class TelldusLiveLight(TelldusLiveEntity, Light): """Representation of a light.""" + def __init__(self, hass, device_id): + """Initialize the light.""" + super().__init__(hass, device_id) + self._last_brightness = self.brightness + def changed(self): """A property of the device might have changed.""" - # pylint: disable=attribute-defined-outside-init self._last_brightness = self.brightness super().changed() From 5c4f04e9fc54a192f368be343a7426df55839d08 Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Fri, 16 Dec 2016 08:51:08 +0200 Subject: [PATCH 123/141] Fix webostv component to accept any custom sources (#4915) Updated the schema check to accept any string Search custom sources in app title and app id The makes the short list redundant and thus removed Tested by adding livetv, netflix, youtube, makovod and others This is also compatible with the list that was supported till now so current users won't see any difference. Signed-off-by: Roi Dayan --- .../components/media_player/webostv.py | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/media_player/webostv.py b/homeassistant/components/media_player/webostv.py index e131cad97cd..40792c338b2 100644 --- a/homeassistant/components/media_player/webostv.py +++ b/homeassistant/components/media_player/webostv.py @@ -41,19 +41,9 @@ SUPPORT_WEBOSTV = SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | \ MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1) -WEBOS_APP_LIVETV = 'com.webos.app.livetv' -WEBOS_APP_YOUTUBE = 'youtube.leanback.v4' -WEBOS_APP_MAKO = 'makotv' - -WEBOS_APPS_SHORT = { - 'livetv': WEBOS_APP_LIVETV, - 'youtube': WEBOS_APP_YOUTUBE, - 'makotv': WEBOS_APP_MAKO -} - CUSTOMIZE_SCHEMA = vol.Schema({ vol.Optional(CONF_SOURCES): - vol.All(cv.ensure_list, [vol.In(WEBOS_APPS_SHORT)]), + vol.All(cv.ensure_list, [cv.string]), }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -175,20 +165,16 @@ class LgWebOSDevice(MediaPlayerDevice): self._source_list = {} self._app_list = {} - custom_sources = [] - for source in self._customize.get(CONF_SOURCES, []): - app_id = WEBOS_APPS_SHORT.get(source, None) - if app_id: - custom_sources.append(app_id) - else: - custom_sources.append(source) + custom_sources = self._customize.get(CONF_SOURCES, []) for app in self._client.get_apps(): self._app_list[app['id']] = app if app['id'] == self._current_source_id: self._current_source = app['title'] self._source_list[app['title']] = app - if app['id'] in custom_sources: + elif (app['id'] in custom_sources or + any(word in app['title'] for word in custom_sources) or + any(word in app['id'] for word in custom_sources)): self._source_list[app['title']] = app for source in self._client.get_inputs(): From 9f9b87692a3176719990a8d12e01334c9efba4f4 Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Fri, 16 Dec 2016 01:55:51 -0500 Subject: [PATCH 124/141] add manual option to prevent scheduled tests. (#4906) --- homeassistant/components/sensor/fastdotcom.py | 13 ++++++++----- homeassistant/components/sensor/speedtest.py | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/sensor/fastdotcom.py b/homeassistant/components/sensor/fastdotcom.py index 0390ea0e9d6..a055d1795e1 100644 --- a/homeassistant/components/sensor/fastdotcom.py +++ b/homeassistant/components/sensor/fastdotcom.py @@ -22,6 +22,7 @@ CONF_SECOND = 'second' CONF_MINUTE = 'minute' CONF_HOUR = 'hour' CONF_DAY = 'day' +CONF_MANUAL = 'manual' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_SECOND, default=[0]): @@ -32,6 +33,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 23))]), vol.Optional(CONF_DAY): vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(1, 31))]), + vol.Optional(CONF_MANUAL, default=False): cv.boolean, }) @@ -104,11 +106,12 @@ class SpeedtestData(object): def __init__(self, hass, config): """Initialize the data object.""" self.data = None - track_time_change(hass, self.update, - second=config.get(CONF_SECOND), - minute=config.get(CONF_MINUTE), - hour=config.get(CONF_HOUR), - day=config.get(CONF_DAY)) + if not config.get(CONF_MANUAL): + track_time_change(hass, self.update, + second=config.get(CONF_SECOND), + minute=config.get(CONF_MINUTE), + hour=config.get(CONF_HOUR), + day=config.get(CONF_DAY)) def update(self, now): """Get the latest data from fast.com.""" diff --git a/homeassistant/components/sensor/speedtest.py b/homeassistant/components/sensor/speedtest.py index 3087c74d474..dff6f1c9dde 100644 --- a/homeassistant/components/sensor/speedtest.py +++ b/homeassistant/components/sensor/speedtest.py @@ -31,6 +31,7 @@ CONF_MINUTE = 'minute' CONF_HOUR = 'hour' CONF_DAY = 'day' CONF_SERVER_ID = 'server_id' +CONF_MANUAL = 'manual' SENSOR_TYPES = { 'ping': ['Ping', 'ms'], @@ -50,6 +51,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(0, 23))]), vol.Optional(CONF_DAY): vol.All(cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(1, 31))]), + vol.Optional(CONF_MANUAL, default=False): cv.boolean, }) @@ -135,11 +137,12 @@ class SpeedtestData(object): """Initialize the data object.""" self.data = None self._server_id = config.get(CONF_SERVER_ID) - track_time_change(hass, self.update, - second=config.get(CONF_SECOND), - minute=config.get(CONF_MINUTE), - hour=config.get(CONF_HOUR), - day=config.get(CONF_DAY)) + if not config.get(CONF_MANUAL): + track_time_change(hass, self.update, + second=config.get(CONF_SECOND), + minute=config.get(CONF_MINUTE), + hour=config.get(CONF_HOUR), + day=config.get(CONF_DAY)) def update(self, now): """Get the latest data from speedtest.net.""" From a0b2105ea032c953195012928953694b214c5755 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 16 Dec 2016 09:10:48 +0100 Subject: [PATCH 125/141] Add voicerss for TTS (#4916) * Add voicerss for TTS * add unittests * fix tests * fix status bug in google/voicerss * remove ssl --- homeassistant/components/tts/google.py | 4 +- homeassistant/components/tts/voicerss.py | 120 +++++++++++++++++ tests/components/tts/test_voicerss.py | 162 +++++++++++++++++++++++ 3 files changed, 284 insertions(+), 2 deletions(-) create mode 100644 homeassistant/components/tts/voicerss.py create mode 100644 tests/components/tts/test_voicerss.py diff --git a/homeassistant/components/tts/google.py b/homeassistant/components/tts/google.py index 92794cd00b6..49d53961062 100644 --- a/homeassistant/components/tts/google.py +++ b/homeassistant/components/tts/google.py @@ -92,8 +92,8 @@ class GoogleProvider(Provider): ) if request.status != 200: - _LOGGER.error("Error %d on load url %s", request.code, - request.url) + _LOGGER.error("Error %d on load url %s", + request.status, request.url) return (None, None) data += yield from request.read() diff --git a/homeassistant/components/tts/voicerss.py b/homeassistant/components/tts/voicerss.py new file mode 100644 index 00000000000..728a1996a5d --- /dev/null +++ b/homeassistant/components/tts/voicerss.py @@ -0,0 +1,120 @@ +""" +Support for the voicerss speech service. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/tts/voicerss/ +""" +import asyncio +import logging + +import aiohttp +import async_timeout +import voluptuous as vol + +from homeassistant.const import CONF_API_KEY +from homeassistant.components.tts import Provider, PLATFORM_SCHEMA, CONF_LANG +from homeassistant.helpers.aiohttp_client import async_get_clientsession +import homeassistant.helpers.config_validation as cv + + +_LOGGER = logging.getLogger(__name__) + +VOICERSS_API_URL = "https://api.voicerss.org/" + +SUPPORT_LANGUAGES = [ + 'ca-es', 'zh-cn', 'zh-hk', 'zh-tw', 'da-dk', 'nl-nl', 'en-au', 'en-ca', + 'en-gb', 'en-in', 'en-us', 'fi-fi', 'fr-ca', 'fr-fr', 'de-de', 'it-it', + 'ja-jp', 'ko-kr', 'nb-no', 'pl-pl', 'pt-br', 'pt-pt', 'ru-ru', 'es-mx', + 'es-es', 'sv-se', +] + +SUPPORT_CODECS = [ + 'mp3', 'wav', 'aac', 'ogg', 'caf' +] + +SUPPORT_FORMATS = [ + '8khz_8bit_mono', '8khz_8bit_stereo', '8khz_16bit_mono', + '8khz_16bit_stereo', '11khz_8bit_mono', '11khz_8bit_stereo', + '11khz_16bit_mono', '11khz_16bit_stereo', '12khz_8bit_mono', + '12khz_8bit_stereo', '12khz_16bit_mono', '12khz_16bit_stereo', + '16khz_8bit_mono', '16khz_8bit_stereo', '16khz_16bit_mono', + '16khz_16bit_stereo', '22khz_8bit_mono', '22khz_8bit_stereo', + '22khz_16bit_mono', '22khz_16bit_stereo', '24khz_8bit_mono', + '24khz_8bit_stereo', '24khz_16bit_mono', '24khz_16bit_stereo', + '32khz_8bit_mono', '32khz_8bit_stereo', '32khz_16bit_mono', + '32khz_16bit_stereo', '44khz_8bit_mono', '44khz_8bit_stereo', + '44khz_16bit_mono', '44khz_16bit_stereo', '48khz_8bit_mono', + '48khz_8bit_stereo', '48khz_16bit_mono', '48khz_16bit_stereo', + 'alaw_8khz_mono', 'alaw_8khz_stereo', 'alaw_11khz_mono', + 'alaw_11khz_stereo', 'alaw_22khz_mono', 'alaw_22khz_stereo', + 'alaw_44khz_mono', 'alaw_44khz_stereo', 'ulaw_8khz_mono', + 'ulaw_8khz_stereo', 'ulaw_11khz_mono', 'ulaw_11khz_stereo', + 'ulaw_22khz_mono', 'ulaw_22khz_stereo', 'ulaw_44khz_mono', + 'ulaw_44khz_stereo', +] + +CONF_CODEC = 'codec' +CONF_FORMAT = 'format' + +DEFAULT_LANG = 'en-us' +DEFAULT_CODEC = 'mp3' +DEFAULT_FORMAT = '8khz_8bit_mono' + + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_API_KEY): cv.string, + vol.Optional(CONF_LANG, default=DEFAULT_LANG): vol.In(SUPPORT_LANGUAGES), + vol.Optional(CONF_CODEC, default=DEFAULT_CODEC): vol.In(SUPPORT_CODECS), + vol.Optional(CONF_FORMAT, default=DEFAULT_FORMAT): vol.In(SUPPORT_FORMATS), +}) + + +@asyncio.coroutine +def async_get_engine(hass, config): + """Setup VoiceRSS speech component.""" + return VoiceRSSProvider(hass, config) + + +class VoiceRSSProvider(Provider): + """VoiceRSS speech api provider.""" + + def __init__(self, hass, conf): + """Init VoiceRSS TTS service.""" + self.hass = hass + self.extension = conf.get(CONF_CODEC) + + self.params = { + 'key': conf.get(CONF_API_KEY), + 'hl': conf.get(CONF_LANG), + 'c': (conf.get(CONF_CODEC)).upper(), + 'f': conf.get(CONF_FORMAT), + } + + @asyncio.coroutine + def async_get_tts_audio(self, message): + """Load TTS from voicerss.""" + websession = async_get_clientsession(self.hass) + + request = None + try: + with async_timeout.timeout(10, loop=self.hass.loop): + request = yield from websession.post( + VOICERSS_API_URL, params=self.params, + data=bytes(message, 'utf-8') + ) + + if request.status != 200: + _LOGGER.error("Error %d on load url %s", + request.status, request.url) + return (None, None) + data = yield from request.read() + + except (asyncio.TimeoutError, aiohttp.errors.ClientError): + _LOGGER.error("Timeout for voicerss api.") + return (None, None) + + finally: + if request is not None: + yield from request.release() + + return (self.extension, data) diff --git a/tests/components/tts/test_voicerss.py b/tests/components/tts/test_voicerss.py new file mode 100644 index 00000000000..44ce0d6739f --- /dev/null +++ b/tests/components/tts/test_voicerss.py @@ -0,0 +1,162 @@ +"""The tests for the VoiceRSS speech platform.""" +import asyncio +import os +import shutil + +import homeassistant.components.tts as tts +from homeassistant.components.media_player import ( + SERVICE_PLAY_MEDIA, ATTR_MEDIA_CONTENT_ID, DOMAIN as DOMAIN_MP) +from homeassistant.bootstrap import setup_component + +from tests.common import ( + get_test_home_assistant, assert_setup_component, mock_service) + + +class TestTTSVoiceRSSPlatform(object): + """Test the voicerss speech component.""" + + def setup_method(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + + self.url = "https://api.voicerss.org/" + self.url_param = { + 'key': '1234567xx', + 'hl': 'en-us', + 'c': 'MP3', + 'f': '8khz_8bit_mono', + } + + def teardown_method(self): + """Stop everything that was started.""" + default_tts = self.hass.config.path(tts.DEFAULT_CACHE_DIR) + if os.path.isdir(default_tts): + shutil.rmtree(default_tts) + + self.hass.stop() + + def test_setup_component(self): + """Test setup component.""" + config = { + tts.DOMAIN: { + 'platform': 'voicerss', + 'api_key': '1234567xx' + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + def test_setup_component_without_api_key(self): + """Test setup component without api key.""" + config = { + tts.DOMAIN: { + 'platform': 'voicerss', + } + } + + with assert_setup_component(0, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + def test_service_say(self, aioclient_mock): + """Test service call say.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + aioclient_mock.post( + self.url, params=self.url_param, status=200, content=b'test') + + config = { + tts.DOMAIN: { + 'platform': 'voicerss', + 'api_key': '1234567xx', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'voicerss_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert len(aioclient_mock.mock_calls) == 1 + assert calls[0].data[ATTR_MEDIA_CONTENT_ID].find(".mp3") != -1 + + def test_service_say_german(self, aioclient_mock): + """Test service call say with german code.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + self.url_param['hl'] = 'de-de' + aioclient_mock.post( + self.url, params=self.url_param, status=200, content=b'test') + + config = { + tts.DOMAIN: { + 'platform': 'voicerss', + 'api_key': '1234567xx', + 'language': 'de-de', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'voicerss_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 1 + assert len(aioclient_mock.mock_calls) == 1 + + def test_service_say_error(self, aioclient_mock): + """Test service call say with http response 400.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + aioclient_mock.post( + self.url, params=self.url_param, status=400, content=b'test') + + config = { + tts.DOMAIN: { + 'platform': 'voicerss', + 'api_key': '1234567xx', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'voicerss_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 0 + assert len(aioclient_mock.mock_calls) == 1 + + def test_service_say_timeout(self, aioclient_mock): + """Test service call say with http timeout.""" + calls = mock_service(self.hass, DOMAIN_MP, SERVICE_PLAY_MEDIA) + + aioclient_mock.post( + self.url, params=self.url_param, exc=asyncio.TimeoutError()) + + config = { + tts.DOMAIN: { + 'platform': 'voicerss', + 'api_key': '1234567xx', + } + } + + with assert_setup_component(1, tts.DOMAIN): + setup_component(self.hass, tts.DOMAIN, config) + + self.hass.services.call(tts.DOMAIN, 'voicerss_say', { + tts.ATTR_MESSAGE: "I person is on front of your door.", + }) + self.hass.block_till_done() + + assert len(calls) == 0 + assert len(aioclient_mock.mock_calls) == 1 From b318a033bbf7f71538e865552df01f9502a30a6f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 16 Dec 2016 00:10:56 -0800 Subject: [PATCH 126/141] Cast fix (#4939) * Update frontend * Fix exception on cast startup --- homeassistant/components/frontend/version.py | 2 +- .../frontend/www_static/frontend.html | 8 ++++---- .../frontend/www_static/frontend.html.gz | Bin 130940 -> 131040 bytes .../www_static/home-assistant-polymer | 2 +- .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2326 -> 2324 bytes homeassistant/components/media_player/cast.py | 6 +++--- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index f316a07dab9..6c480254cb8 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -2,7 +2,7 @@ FINGERPRINTS = { "core.js": "ad1ebcd0614c98a390d982087a7ca75c", - "frontend.html": "920bb20410f9a1b8458600b15a1d40ae", + "frontend.html": "826ee6a4b39c939e31aa468b1ef618f9", "mdi.html": "46a76f877ac9848899b8ed382427c16f", "micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a", "panels/ha-panel-dev-event.html": "c2d5ec676be98d4474d19f94d0262c1e", diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index 474db7d63c4..d8ab01b320f 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -1,5 +1,5 @@ - \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/frontend.html.gz b/homeassistant/components/frontend/www_static/frontend.html.gz index 7d29d3b9612a0a75b3204479f3f6ee038cf9e6bf..3708f52a28065a5713abca93a753c689e6d1d4b8 100644 GIT binary patch delta 123746 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%0DSU2}NhXPgG-1-($bTeUYLLC7b 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 delta 123623 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 diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index 0f3b98cab46..7e96e0dbed6 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -236,9 +236,9 @@ class CastDevice(MediaPlayerDevice): @property def media_position(self): """Position of current playing media in seconds.""" - if self.media_status is None or not ( - self.media_status.player_is_playing or - self.media_status.player_is_idle): + if self.media_status is None or self.media_status_received is None or \ + not (self.media_status.player_is_playing or + self.media_status.player_is_idle): return None position = self.media_status.current_time From 32dc51897190ab06e6c0e9c0b3f2760aa3ffe824 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Fri, 16 Dec 2016 10:16:46 -0600 Subject: [PATCH 127/141] Use Wake-on-LAN to turn on Panasonic Viera TV (#4809) --- .../media_player/panasonic_viera.py | 26 +++++++++++++++---- requirements_all.txt | 1 + 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/media_player/panasonic_viera.py b/homeassistant/components/media_player/panasonic_viera.py index bbac8f243d3..b345fcf4884 100644 --- a/homeassistant/components/media_player/panasonic_viera.py +++ b/homeassistant/components/media_player/panasonic_viera.py @@ -10,16 +10,20 @@ import voluptuous as vol from homeassistant.components.media_player import ( SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, - SUPPORT_TURN_OFF, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, + SUPPORT_TURN_ON, SUPPORT_TURN_OFF, + SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP, MediaPlayerDevice, PLATFORM_SCHEMA) from homeassistant.const import ( CONF_HOST, CONF_NAME, STATE_OFF, STATE_ON, STATE_UNKNOWN, CONF_PORT) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['panasonic_viera==0.2'] +REQUIREMENTS = ['panasonic_viera==0.2', + 'wakeonlan==0.2.2'] _LOGGER = logging.getLogger(__name__) +CONF_MAC = 'mac' + DEFAULT_NAME = 'Panasonic Viera TV' DEFAULT_PORT = 55000 @@ -30,6 +34,7 @@ SUPPORT_VIERATV = SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | \ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_MAC): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, }) @@ -40,6 +45,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Panasonic Viera TV platform.""" from panasonic_viera import RemoteControl + mac = config.get(CONF_MAC) name = config.get(CONF_NAME) port = config.get(CONF_PORT) @@ -51,22 +57,25 @@ def setup_platform(hass, config, add_devices, discovery_info=None): host = vals[0] remote = RemoteControl(host, port) - add_devices([PanasonicVieraTVDevice(name, remote)]) + add_devices([PanasonicVieraTVDevice(mac, name, remote)]) return True host = config.get(CONF_HOST) remote = RemoteControl(host, port) - add_devices([PanasonicVieraTVDevice(name, remote)]) + add_devices([PanasonicVieraTVDevice(mac, name, remote)]) return True class PanasonicVieraTVDevice(MediaPlayerDevice): """Representation of a Panasonic Viera TV.""" - def __init__(self, name, remote): + def __init__(self, mac, name, remote): """Initialize the Panasonic device.""" + from wakeonlan import wol # Save a reference to the imported class + self._wol = wol + self._mac = mac self._name = name self._muted = False self._playing = True @@ -116,8 +125,15 @@ class PanasonicVieraTVDevice(MediaPlayerDevice): @property def supported_media_commands(self): """Flag of media commands that are supported.""" + if self._mac: + return SUPPORT_VIERATV | SUPPORT_TURN_ON return SUPPORT_VIERATV + def turn_on(self): + """Turn on the media player.""" + if self._mac: + self._wol.send_magic_packet(self._mac) + def turn_off(self): """Turn off media player.""" self.send_key('NRC_POWER-ONOFF') diff --git a/requirements_all.txt b/requirements_all.txt index 81b6eef84a4..6bc661d6ba0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -604,6 +604,7 @@ vsure==0.11.1 # homeassistant.components.sensor.vasttrafik vtjp==0.1.11 +# homeassistant.components.media_player.panasonic_viera # homeassistant.components.switch.wake_on_lan wakeonlan==0.2.2 From 8358ab56ea3ce210e837c2bca977b3335191f025 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Fri, 16 Dec 2016 17:36:50 +0100 Subject: [PATCH 128/141] Bugfix asyncio wait (#4946) --- homeassistant/components/input_boolean.py | 3 ++- homeassistant/components/input_select.py | 9 ++++++--- homeassistant/components/input_slider.py | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/input_boolean.py b/homeassistant/components/input_boolean.py index 579e6bade3e..16b2d365976 100644 --- a/homeassistant/components/input_boolean.py +++ b/homeassistant/components/input_boolean.py @@ -95,7 +95,8 @@ def async_setup(hass, config): attr = 'async_toggle' tasks = [getattr(input_b, attr)() for input_b in target_inputs] - yield from asyncio.wait(tasks, loop=hass.loop) + if tasks: + yield from asyncio.wait(tasks, loop=hass.loop) hass.services.async_register( DOMAIN, SERVICE_TURN_OFF, async_handler_service, schema=SERVICE_SCHEMA) diff --git a/homeassistant/components/input_select.py b/homeassistant/components/input_select.py index 9b563d271f5..bd25a74ae3f 100644 --- a/homeassistant/components/input_select.py +++ b/homeassistant/components/input_select.py @@ -113,7 +113,8 @@ def async_setup(hass, config): tasks = [input_select.async_select_option(call.data[ATTR_OPTION]) for input_select in target_inputs] - yield from asyncio.wait(tasks, loop=hass.loop) + if tasks: + yield from asyncio.wait(tasks, loop=hass.loop) hass.services.async_register( DOMAIN, SERVICE_SELECT_OPTION, async_select_option_service, @@ -126,7 +127,8 @@ def async_setup(hass, config): tasks = [input_select.async_offset_index(1) for input_select in target_inputs] - yield from asyncio.wait(tasks, loop=hass.loop) + if tasks: + yield from asyncio.wait(tasks, loop=hass.loop) hass.services.async_register( DOMAIN, SERVICE_SELECT_NEXT, async_select_next_service, @@ -139,7 +141,8 @@ def async_setup(hass, config): tasks = [input_select.async_offset_index(-1) for input_select in target_inputs] - yield from asyncio.wait(tasks, loop=hass.loop) + if tasks: + yield from asyncio.wait(tasks, loop=hass.loop) hass.services.async_register( DOMAIN, SERVICE_SELECT_PREVIOUS, async_select_previous_service, diff --git a/homeassistant/components/input_slider.py b/homeassistant/components/input_slider.py index eccffb5ae29..d2453a97d14 100644 --- a/homeassistant/components/input_slider.py +++ b/homeassistant/components/input_slider.py @@ -105,7 +105,8 @@ def async_setup(hass, config): tasks = [input_slider.async_select_value(call.data[ATTR_VALUE]) for input_slider in target_inputs] - yield from asyncio.wait(tasks, loop=hass.loop) + if tasks: + yield from asyncio.wait(tasks, loop=hass.loop) hass.services.async_register( DOMAIN, SERVICE_SELECT_VALUE, async_select_value_service, From 326cc83a17d344ea60ccaa1ef8295efaebf82f21 Mon Sep 17 00:00:00 2001 From: Ashura Date: Fri, 16 Dec 2016 18:41:31 +0100 Subject: [PATCH 129/141] [media_player.braviatv] Add turn on capabilities. (#4938) --- homeassistant/components/media_player/braviatv.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/media_player/braviatv.py b/homeassistant/components/media_player/braviatv.py index dbcecd6097a..004682b402e 100644 --- a/homeassistant/components/media_player/braviatv.py +++ b/homeassistant/components/media_player/braviatv.py @@ -13,7 +13,7 @@ import voluptuous as vol from homeassistant.loader import get_component from homeassistant.components.media_player import ( - SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, + SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, SUPPORT_TURN_ON, SUPPORT_TURN_OFF, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_SET, SUPPORT_SELECT_SOURCE, MediaPlayerDevice, PLATFORM_SCHEMA) @@ -40,7 +40,8 @@ _LOGGER = logging.getLogger(__name__) SUPPORT_BRAVIA = SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | \ SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_SET | \ SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \ - SUPPORT_TURN_OFF | SUPPORT_SELECT_SOURCE + SUPPORT_TURN_ON | SUPPORT_TURN_OFF | \ + SUPPORT_SELECT_SOURCE PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, From 6d6abab358e30f558a01dfc44f0c2f73daad135c Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sat, 17 Dec 2016 00:51:06 +0100 Subject: [PATCH 130/141] Async logging file handler (#4901) * Async logging file handler * add time rotation handle * new layout * address paulus comments * fix lint --- homeassistant/bootstrap.py | 6 ++- homeassistant/util/logging.py | 95 +++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 95bb7cee24a..ac9153ce685 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -20,6 +20,7 @@ import homeassistant.loader as loader import homeassistant.util.package as pkg_util from homeassistant.util.async import ( run_coroutine_threadsafe, run_callback_threadsafe) +from homeassistant.util.logging import AsyncHandler from homeassistant.util.yaml import clear_secret_cache from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT from homeassistant.exceptions import HomeAssistantError @@ -548,8 +549,11 @@ def enable_logging(hass: core.HomeAssistant, verbose: bool=False, err_handler.setFormatter( logging.Formatter('%(asctime)s %(name)s: %(message)s', datefmt='%y-%m-%d %H:%M:%S')) + + async_handler = AsyncHandler(hass.loop, err_handler) + logger = logging.getLogger('') - logger.addHandler(err_handler) + logger.addHandler(async_handler) logger.setLevel(logging.INFO) else: diff --git a/homeassistant/util/logging.py b/homeassistant/util/logging.py index d324e7253b7..70dd9e36d21 100644 --- a/homeassistant/util/logging.py +++ b/homeassistant/util/logging.py @@ -1,5 +1,9 @@ """Logging utilities.""" +import asyncio import logging +import threading + +from .async import run_coroutine_threadsafe class HideSensitiveDataFilter(logging.Filter): @@ -15,3 +19,94 @@ class HideSensitiveDataFilter(logging.Filter): record.msg = record.msg.replace(self.text, '*******') return True + + +# pylint: disable=invalid-name +class AsyncHandler(object): + """Logging handler wrapper to add a async layer.""" + + def __init__(self, loop, handler): + """Initialize async logging handler wrapper.""" + self.handler = handler + self.loop = loop + self._queue = asyncio.Queue(loop=loop) + self._thread = threading.Thread(target=self._process) + + # Delegate from handler + self.setLevel = handler.setLevel + self.setFormatter = handler.setFormatter + self.addFilter = handler.addFilter + self.removeFilter = handler.removeFilter + self.filter = handler.filter + self.flush = handler.flush + self.handle = handler.handle + self.handleError = handler.handleError + self.format = handler.format + + def close(self): + """Wrap close to handler.""" + self.emit(None) + + def open(self): + """Wrap open to handler.""" + self._thread.start() + self.handler.open() + + def emit(self, record): + """Process a record.""" + ident = self.loop.__dict__.get("_thread_ident") + + # inside eventloop + if ident is not None and ident == threading.get_ident(): + self._queue.put_nowait(record) + # from a thread/executor + else: + self.loop.call_soon_threadsafe(self._queue.put_nowait, record) + + def __repr__(self): + """String name of this.""" + return str(self.handler) + + def _process(self): + """Process log in a thread.""" + while True: + record = run_coroutine_threadsafe( + self._queue.get(), self.loop).result() + + if record is None: + self.handler.close() + return + + self.handler.emit(record) + + def createLock(self): + """Ignore lock stuff.""" + pass + + def acquire(self): + """Ignore lock stuff.""" + pass + + def release(self): + """Ignore lock stuff.""" + pass + + @property + def level(self): + """Wrap property level to handler.""" + return self.handler.level + + @property + def formatter(self): + """Wrap property formatter to handler.""" + return self.handler.formatter + + @property + def name(self): + """Wrap property set_name to handler.""" + return self.handler.get_name() + + @name.setter + def set_name(self, name): + """Wrap property get_name to handler.""" + self.handler.name = name From 78f6cfd1ebbd3a5f62456c63809a4da38ea1118c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 16 Dec 2016 22:03:45 -0800 Subject: [PATCH 131/141] Update coverage --- .coveragerc | 1 + 1 file changed, 1 insertion(+) diff --git a/.coveragerc b/.coveragerc index d929d50271b..1a62d7e60f3 100644 --- a/.coveragerc +++ b/.coveragerc @@ -167,6 +167,7 @@ omit = homeassistant/components/discovery.py homeassistant/components/downloader.py homeassistant/components/emoncms_history.py + homeassistant/components/emulated_hue/upnp.py homeassistant/components/fan/mqtt.py homeassistant/components/feedreader.py homeassistant/components/foursquare.py From 6c524594c14dfb5a98b2ef786b71f69ed3304fba Mon Sep 17 00:00:00 2001 From: Daniel Perna Date: Sat, 17 Dec 2016 07:34:13 +0100 Subject: [PATCH 132/141] Fixing issue #4899 (#4947) --- homeassistant/components/notify/nfandroidtv.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/notify/nfandroidtv.py b/homeassistant/components/notify/nfandroidtv.py index 2ba9e7c72be..cd44b1f0cd3 100644 --- a/homeassistant/components/notify/nfandroidtv.py +++ b/homeassistant/components/notify/nfandroidtv.py @@ -77,7 +77,6 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.In(TRANSPARENCIES.keys()), vol.Optional(CONF_COLOR, default=DEFAULT_COLOR): vol.In(COLORS.keys()), - vol.Optional(CONF_COLOR, default=DEFAULT_COLOR): cv.string, vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.Coerce(int), vol.Optional(CONF_INTERRUPT, default=DEFAULT_INTERRUPT): cv.boolean, }) From 831cad4220754e7112c0bb27763df391d887aad2 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 17 Dec 2016 01:24:35 -0600 Subject: [PATCH 133/141] Use Wake-on-LAN to turn on LG webOS TV (#4808) --- .../components/media_player/webostv.py | 78 ++++++++++++------- requirements_all.txt | 4 + 2 files changed, 54 insertions(+), 28 deletions(-) diff --git a/homeassistant/components/media_player/webostv.py b/homeassistant/components/media_player/webostv.py index 40792c338b2..a2f49cc3f21 100644 --- a/homeassistant/components/media_player/webostv.py +++ b/homeassistant/components/media_player/webostv.py @@ -1,5 +1,5 @@ """ -Support for interface with an LG WebOS TV. +Support for interface with an LG webOS Smart TV. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/media_player.webostv/ @@ -12,31 +12,35 @@ import voluptuous as vol import homeassistant.util as util from homeassistant.components.media_player import ( + SUPPORT_TURN_ON, SUPPORT_TURN_OFF, SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PREVIOUS_TRACK, - SUPPORT_TURN_OFF, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, + SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_SELECT_SOURCE, SUPPORT_PLAY_MEDIA, MEDIA_TYPE_CHANNEL, MediaPlayerDevice, PLATFORM_SCHEMA) from homeassistant.const import ( - CONF_HOST, CONF_CUSTOMIZE, STATE_OFF, STATE_PLAYING, STATE_PAUSED, + CONF_HOST, CONF_MAC, CONF_CUSTOMIZE, STATE_OFF, + STATE_PLAYING, STATE_PAUSED, STATE_UNKNOWN, CONF_NAME) from homeassistant.loader import get_component import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['https://github.com/TheRealLink/pylgtv' '/archive/v0.1.2.zip' - '#pylgtv==0.1.2'] + '#pylgtv==0.1.2', + 'websockets==3.2', + 'wakeonlan==0.2.2'] -_CONFIGURING = {} +_CONFIGURING = {} # type: Dict[str, str] _LOGGER = logging.getLogger(__name__) CONF_SOURCES = 'sources' -DEFAULT_NAME = 'LG WebOS Smart TV' +DEFAULT_NAME = 'LG webOS Smart TV' -SUPPORT_WEBOSTV = SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | \ - SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | \ - SUPPORT_NEXT_TRACK | SUPPORT_TURN_OFF | \ - SUPPORT_SELECT_SOURCE | SUPPORT_PLAY_MEDIA +SUPPORT_WEBOSTV = SUPPORT_TURN_OFF | \ + SUPPORT_NEXT_TRACK | SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | \ + SUPPORT_VOLUME_MUTE | SUPPORT_VOLUME_STEP | \ + SUPPORT_SELECT_SOURCE | SUPPORT_PLAY_MEDIA MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=1) @@ -49,6 +53,7 @@ CUSTOMIZE_SCHEMA = vol.Schema({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_HOST): cv.string, + vol.Optional(CONF_MAC): cv.string, vol.Optional(CONF_CUSTOMIZE, default={}): CUSTOMIZE_SCHEMA, }) @@ -69,15 +74,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if host in _CONFIGURING: return + mac = config.get(CONF_MAC) name = config.get(CONF_NAME) customize = config.get(CONF_CUSTOMIZE) - setup_tv(host, name, customize, hass, add_devices) + setup_tv(host, mac, name, customize, hass, add_devices) -def setup_tv(host, name, customize, hass, add_devices): - """Setup a phue bridge based on host parameter.""" +def setup_tv(host, mac, name, customize, hass, add_devices): + """Setup a LG WebOS TV based on host parameter.""" from pylgtv import WebOsClient from pylgtv import PyLGTVPairException + from websockets.exceptions import ConnectionClosed client = WebOsClient(host) @@ -88,15 +95,16 @@ def setup_tv(host, name, customize, hass, add_devices): client.register() except PyLGTVPairException: _LOGGER.warning( - "Connected to LG WebOS TV %s but not paired", host) + "Connected to LG webOS TV %s but not paired", host) return - except OSError: + except (OSError, ConnectionClosed): _LOGGER.error("Unable to connect to host %s", host) return else: # Not registered, request configuration. - _LOGGER.warning("LG WebOS TV %s needs to be paired", host) - request_configuration(host, name, customize, hass, add_devices) + _LOGGER.warning("LG webOS TV %s needs to be paired", host) + request_configuration( + host, mac, name, customize, hass, add_devices) return # If we came here and configuring this host, mark as done. @@ -105,10 +113,11 @@ def setup_tv(host, name, customize, hass, add_devices): configurator = get_component('configurator') configurator.request_done(request_id) - add_devices([LgWebOSDevice(host, name, customize)]) + add_devices([LgWebOSDevice(host, mac, name, customize)], True) -def request_configuration(host, name, customize, hass, add_devices): +def request_configuration( + host, mac, name, customize, hass, add_devices): """Request configuration steps from the user.""" configurator = get_component('configurator') @@ -121,10 +130,10 @@ def request_configuration(host, name, customize, hass, add_devices): # pylint: disable=unused-argument def lgtv_configuration_callback(data): """The actions to do when our configuration callback is called.""" - setup_tv(host, name, customize, hass, add_devices) + setup_tv(host, mac, name, customize, hass, add_devices) _CONFIGURING[host] = configurator.request_config( - hass, 'LG WebOS TV', lgtv_configuration_callback, + hass, name, lgtv_configuration_callback, description='Click start and accept the pairing request on your TV.', description_image='/static/images/config_webos.png', submit_caption='Start pairing request' @@ -134,10 +143,13 @@ def request_configuration(host, name, customize, hass, add_devices): class LgWebOSDevice(MediaPlayerDevice): """Representation of a LG WebOS TV.""" - def __init__(self, host, name, customize): + def __init__(self, host, mac, name, customize): """Initialize the webos device.""" from pylgtv import WebOsClient + from wakeonlan import wol self._client = WebOsClient(host) + self._wol = wol + self._mac = mac self._customize = customize self._name = name @@ -148,15 +160,14 @@ class LgWebOSDevice(MediaPlayerDevice): self._volume = 0 self._current_source = None self._current_source_id = None - self._source_list = None self._state = STATE_UNKNOWN - self._app_list = None - - self.update() + self._source_list = {} + self._app_list = {} @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) def update(self): """Retrieve the latest data.""" + from websockets.exceptions import ConnectionClosed try: self._state = STATE_PLAYING self._muted = self._client.get_muted() @@ -183,7 +194,7 @@ class LgWebOSDevice(MediaPlayerDevice): app = self._app_list[source['appId']] self._source_list[app['title']] = app - except OSError: + except (OSError, ConnectionClosed): self._state = STATE_OFF @property @@ -231,12 +242,23 @@ class LgWebOSDevice(MediaPlayerDevice): @property def supported_media_commands(self): """Flag of media commands that are supported.""" + if self._mac: + return SUPPORT_WEBOSTV | SUPPORT_TURN_ON return SUPPORT_WEBOSTV def turn_off(self): """Turn off media player.""" + from websockets.exceptions import ConnectionClosed self._state = STATE_OFF - self._client.power_off() + try: + self._client.power_off() + except (OSError, ConnectionClosed): + pass + + def turn_on(self): + """Turn on the media player.""" + if self._mac: + self._wol.send_magic_packet(self._mac) def volume_up(self): """Volume up the media player.""" diff --git a/requirements_all.txt b/requirements_all.txt index 6bc661d6ba0..6649fc058d9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -605,12 +605,16 @@ vsure==0.11.1 vtjp==0.1.11 # homeassistant.components.media_player.panasonic_viera +# homeassistant.components.media_player.webostv # homeassistant.components.switch.wake_on_lan wakeonlan==0.2.2 # homeassistant.components.media_player.gpmdp websocket-client==0.37.0 +# homeassistant.components.media_player.webostv +websockets==3.2 + # homeassistant.components.zigbee xbee-helper==0.0.7 From 4abcaea4b7b22c9c5ba980b8496c3968fe7a5e3d Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sat, 17 Dec 2016 19:29:24 +0100 Subject: [PATCH 134/141] Upgrade python-telegram-bot to 5.3.0 (#4955) --- homeassistant/components/notify/telegram.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/notify/telegram.py b/homeassistant/components/notify/telegram.py index 11719f8758a..c133506e775 100644 --- a/homeassistant/components/notify/telegram.py +++ b/homeassistant/components/notify/telegram.py @@ -19,7 +19,7 @@ from homeassistant.const import ( _LOGGER = logging.getLogger(__name__) -REQUIREMENTS = ['python-telegram-bot==5.2.0'] +REQUIREMENTS = ['python-telegram-bot==5.3.0'] ATTR_PHOTO = 'photo' ATTR_DOCUMENT = 'document' diff --git a/requirements_all.txt b/requirements_all.txt index 6649fc058d9..3c800e03737 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -482,7 +482,7 @@ python-pushover==0.2 python-synology==0.1.0 # homeassistant.components.notify.telegram -python-telegram-bot==5.2.0 +python-telegram-bot==5.3.0 # homeassistant.components.sensor.twitch python-twitch==1.3.0 From 44c4b25f2b51388ef5e9e4b7fe3905dbf7661872 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sat, 17 Dec 2016 19:29:36 +0100 Subject: [PATCH 135/141] Upgrade astral to 1.3.3 (#4956) --- homeassistant/components/sun.py | 3 +-- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sun.py b/homeassistant/components/sun.py index 8a98bc0c6df..92349be6376 100644 --- a/homeassistant/components/sun.py +++ b/homeassistant/components/sun.py @@ -17,8 +17,7 @@ from homeassistant.util import dt as dt_util import homeassistant.helpers.config_validation as cv import homeassistant.util as util - -REQUIREMENTS = ['astral==1.3.2'] +REQUIREMENTS = ['astral==1.3.3'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 3c800e03737..7621411130f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -43,7 +43,7 @@ apcaccess==0.0.4 apns2==0.1.1 # homeassistant.components.sun -astral==1.3.2 +astral==1.3.3 # homeassistant.components.sensor.linux_battery batinfo==0.4.2 From 60ef0153a29828b6880fe7f7828ae4f9f7b67ac8 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sat, 17 Dec 2016 19:30:54 +0100 Subject: [PATCH 136/141] Upgrade Sphinx to 1.5.1 (#4957) --- requirements_docs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_docs.txt b/requirements_docs.txt index b39476859f2..e5331727ec9 100644 --- a/requirements_docs.txt +++ b/requirements_docs.txt @@ -1,3 +1,3 @@ -Sphinx==1.4.9 +Sphinx==1.5.1 sphinx-autodoc-typehints==1.1.0 sphinx-autodoc-annotation==1.0.post1 From b08b376aa7c71c3598663d5be87c5d3781123059 Mon Sep 17 00:00:00 2001 From: Erik Eriksson Date: Sat, 17 Dec 2016 21:14:04 +0100 Subject: [PATCH 137/141] eliqonline lib upgrade (#4948) --- homeassistant/components/sensor/eliqonline.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/eliqonline.py b/homeassistant/components/sensor/eliqonline.py index 421940b9c7d..7029be9fca2 100644 --- a/homeassistant/components/sensor/eliqonline.py +++ b/homeassistant/components/sensor/eliqonline.py @@ -14,7 +14,7 @@ from homeassistant.const import (CONF_ACCESS_TOKEN, CONF_NAME, STATE_UNKNOWN) from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['eliqonline==1.0.12'] +REQUIREMENTS = ['eliqonline==1.0.13'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 7621411130f..b5d803f5c73 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -105,7 +105,7 @@ dsmr_parser==0.4 dweepy==0.2.0 # homeassistant.components.sensor.eliqonline -eliqonline==1.0.12 +eliqonline==1.0.13 # homeassistant.components.enocean enocean==0.31 From 50c8224365613b92c2190947ea58d19b6136193f Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sat, 17 Dec 2016 21:21:52 +0100 Subject: [PATCH 138/141] Bugfix async log handler (#4954) * Bugfix async log handler * fix boostrap test * Use hass.data for store handler and cleanup on async_stop * Update bootstrap.py --- homeassistant/bootstrap.py | 5 +++++ homeassistant/core.py | 12 ++++++++++-- homeassistant/scripts/check_config.py | 3 ++- homeassistant/util/logging.py | 7 ++----- tests/test_bootstrap.py | 5 ++++- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index ac9153ce685..3d03336c0fe 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -529,6 +529,10 @@ def enable_logging(hass: core.HomeAssistant, verbose: bool=False, except ImportError: pass + # AsyncHandler allready exists? + if hass.data.get(core.DATA_ASYNCHANDLER): + return + # Log errors to a file if we have write access to file or config dir err_log_path = hass.config.path(ERROR_LOG_FILENAME) err_path_exists = os.path.isfile(err_log_path) @@ -551,6 +555,7 @@ def enable_logging(hass: core.HomeAssistant, verbose: bool=False, datefmt='%y-%m-%d %H:%M:%S')) async_handler = AsyncHandler(hass.loop, err_handler) + hass.data[core.DATA_ASYNCHANDLER] = async_handler logger = logging.getLogger('') logger.addHandler(async_handler) diff --git a/homeassistant/core.py b/homeassistant/core.py index da4fd2ed102..7daab159f21 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -57,8 +57,8 @@ ENTITY_ID_PATTERN = re.compile(r"^(\w+)\.(\w+)$") # Size of a executor pool EXECUTOR_POOL_SIZE = 10 -# Time for cleanup internal pending tasks -TIME_INTERVAL_TASKS_CLEANUP = 10 +# AsyncHandler for logging +DATA_ASYNCHANDLER = 'log_asynchandler' _LOGGER = logging.getLogger(__name__) @@ -294,6 +294,14 @@ class HomeAssistant(object): yield from self.async_block_till_done() self.executor.shutdown() self.state = CoreState.not_running + + # cleanup async layer from python logging + if self.data.get(DATA_ASYNCHANDLER): + handler = self.data.pop(DATA_ASYNCHANDLER) + logger = logging.getLogger('') + handler.close() + logger.removeHandler(handler) + self.loop.stop() # pylint: disable=no-self-use diff --git a/homeassistant/scripts/check_config.py b/homeassistant/scripts/check_config.py index ace1b4efe83..986630e4db0 100644 --- a/homeassistant/scripts/check_config.py +++ b/homeassistant/scripts/check_config.py @@ -231,7 +231,8 @@ def check(config_path): yaml.yaml.SafeLoader.add_constructor('!secret', yaml._secret_yaml) try: - bootstrap.from_config_file(config_path, skip_pip=True) + with patch('homeassistant.util.logging.AsyncHandler._process'): + bootstrap.from_config_file(config_path, skip_pip=True) res['secret_cache'] = dict(yaml.__SECRET_CACHE) except Exception as err: # pylint: disable=broad-except print(color('red', 'Fatal error while loading config:'), str(err)) diff --git a/homeassistant/util/logging.py b/homeassistant/util/logging.py index 70dd9e36d21..1ddec0bc6a1 100644 --- a/homeassistant/util/logging.py +++ b/homeassistant/util/logging.py @@ -43,15 +43,12 @@ class AsyncHandler(object): self.handleError = handler.handleError self.format = handler.format + self._thread.start() + def close(self): """Wrap close to handler.""" self.emit(None) - def open(self): - """Wrap open to handler.""" - self._thread.start() - self.handler.open() - def emit(self, record): """Process a record.""" ident = self.loop.__dict__.get("_thread_ident") diff --git a/tests/test_bootstrap.py b/tests/test_bootstrap.py index dd3b09d932f..887ef7c2c20 100644 --- a/tests/test_bootstrap.py +++ b/tests/test_bootstrap.py @@ -70,6 +70,8 @@ class TestBootstrap: with mock.patch('os.path.isfile', mock.Mock(return_value=True)), \ mock.patch('os.access', mock.Mock(return_value=True)), \ + mock.patch('homeassistant.bootstrap.enable_logging', + mock.Mock(return_value=True)), \ patch_yaml_files(files, True): self.hass = bootstrap.from_config_file('config.yaml') @@ -286,7 +288,8 @@ class TestBootstrap: assert not bootstrap.setup_component(self.hass, 'comp', {}) assert 'comp' not in self.hass.config.components - def test_home_assistant_core_config_validation(self): + @mock.patch('homeassistant.bootstrap.enable_logging') + def test_home_assistant_core_config_validation(self, log_mock): """Test if we pass in wrong information for HA conf.""" # Extensive HA conf validation testing is done in test_config.py assert None is bootstrap.from_config_dict({ From cc9e5de5031ddac20423d31d2d84086c9d5a9bbd Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 17 Dec 2016 13:00:08 -0800 Subject: [PATCH 139/141] Only report slowness warning once per entity (#4962) --- homeassistant/helpers/entity.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index 87b05ded264..4137a31b8b6 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -79,6 +79,9 @@ class Entity(object): # Owning hass instance. Will be set by EntityComponent hass = None # type: Optional[HomeAssistant] + # If we reported if this entity was slow + _slow_reported = False + @property def should_poll(self) -> bool: """Return True if entity has to be polled for state. @@ -243,7 +246,8 @@ class Entity(object): end = timer() - if end - start > 0.4: + if not self._slow_reported and end - start > 0.4: + self._slow_reported = True _LOGGER.warning('Updating state for %s took %.3f seconds. ' 'Please report platform to the developers at ' 'https://goo.gl/Nvioub', self.entity_id, From 7390f82e1fb1f71126d83a46843032fe59c22a39 Mon Sep 17 00:00:00 2001 From: Georgi Kirichkov Date: Sat, 17 Dec 2016 23:49:43 +0200 Subject: [PATCH 140/141] Updates TP-Link dependency (#4914) * Updates TP-Link switches dependent module Refactors code to use the new module API * Set TP-Link Switch name from the device settings If no name has been set in the configuration file the name set on the device will be used * Removes default name for TP-Link switch Fallback to device alias now works properly * Removes logging * Updates comment to denote support for HS200 switch --- homeassistant/components/switch/tplink.py | 29 +++++++++++++---------- requirements_all.txt | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/switch/tplink.py b/homeassistant/components/switch/tplink.py index bcc1b329fa8..44fecf37e56 100644 --- a/homeassistant/components/switch/tplink.py +++ b/homeassistant/components/switch/tplink.py @@ -1,5 +1,5 @@ """ -Support for TPLink HS100/HS110 smart switch. +Support for TPLink HS100/HS110/HS200 smart switch. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/switch.tplink/ @@ -15,12 +15,10 @@ from homeassistant.const import (CONF_HOST, CONF_NAME) import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['https://github.com/GadgetReactor/pyHS100/archive/' - '1f771b7d8090a91c6a58931532e42730b021cbde.zip#pyHS100==0.2.0'] + '45fc3548882628bcde3e3d365db341849457bef2.zip#pyHS100==0.2.2'] _LOGGER = logging.getLogger(__name__) -DEFAULT_NAME = 'TPLink Switch HS100' - ATTR_CURRENT_CONSUMPTION = 'Current consumption' ATTR_TOTAL_CONSUMPTION = 'Total consumption' ATTR_DAILY_CONSUMPTION = 'Daily consumption' @@ -29,14 +27,14 @@ ATTR_CURRENT = 'Current' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_NAME): cv.string, }) # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the TPLink switch platform.""" - from pyHS100.pyHS100 import SmartPlug + from pyHS100 import SmartPlug host = config.get(CONF_HOST) name = config.get(CONF_NAME) @@ -49,10 +47,15 @@ class SmartPlugSwitch(SwitchDevice): def __init__(self, smartplug, name): """Initialize the switch.""" self.smartplug = smartplug - self._name = name + + # Use the name set on the device if not set + if name is None: + self._name = self.smartplug.alias + else: + self._name = name + self._state = None - self._emeter_present = (smartplug.model == 110) - _LOGGER.debug("Setting up TP-Link Smart Plug HS%i", smartplug.model) + _LOGGER.debug("Setting up TP-Link Smart Plug") # Set up emeter cache self._emeter_params = {} @@ -64,15 +67,15 @@ class SmartPlugSwitch(SwitchDevice): @property def is_on(self): """Return true if switch is on.""" - return self._state == 'ON' + return self.smartplug.is_on def turn_on(self, **kwargs): """Turn the switch on.""" - self.smartplug.state = 'ON' + self.smartplug.turn_on() def turn_off(self): """Turn the switch off.""" - self.smartplug.state = 'OFF' + self.smartplug.turn_off() @property def device_state_attributes(self): @@ -84,7 +87,7 @@ class SmartPlugSwitch(SwitchDevice): try: self._state = self.smartplug.state - if self._emeter_present: + if self.smartplug.has_emeter: emeter_readings = self.smartplug.get_emeter_realtime() self._emeter_params[ATTR_CURRENT_CONSUMPTION] \ diff --git a/requirements_all.txt b/requirements_all.txt index b5d803f5c73..f39a560f2f8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -180,7 +180,7 @@ http://github.com/technicalpickles/python-nest/archive/b8391d2b3cb8682f8b0c2bdff https://github.com/Danielhiversen/flux_led/archive/0.10.zip#flux_led==0.10 # homeassistant.components.switch.tplink -https://github.com/GadgetReactor/pyHS100/archive/1f771b7d8090a91c6a58931532e42730b021cbde.zip#pyHS100==0.2.0 +https://github.com/GadgetReactor/pyHS100/archive/45fc3548882628bcde3e3d365db341849457bef2.zip#pyHS100==0.2.2 # homeassistant.components.switch.dlink https://github.com/LinuxChristian/pyW215/archive/v0.3.7.zip#pyW215==0.3.7 From 35d7f2b8bbb1ddd8e4fe224ac7422ed401568a0a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 17 Dec 2016 14:07:13 -0800 Subject: [PATCH 141/141] Version bump to 0.35.0 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 0a014c0b603..0a93f080df7 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 35 -PATCH_VERSION = '0.dev0' +PATCH_VERSION = '0' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2)