From 5581c6295e0e8d34b40cfa5d2ebec0b8b4711c3d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 13 Jul 2017 10:19:59 -0700 Subject: [PATCH 001/118] Fix iFrame panel test --- tests/components/test_panel_iframe.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/components/test_panel_iframe.py b/tests/components/test_panel_iframe.py index ec1e5bf3650..5f9cdcfa57c 100644 --- a/tests/components/test_panel_iframe.py +++ b/tests/components/test_panel_iframe.py @@ -53,9 +53,7 @@ class TestPanelIframe(unittest.TestCase): }, }) - # 5 dev tools + map are automatically loaded + 2 iframe panels - assert len(self.hass.data[frontend.DATA_PANELS]) == 8 - assert self.hass.data[frontend.DATA_PANELS]['router'] == { + assert self.hass.data[frontend.DATA_PANELS].get('router') == { 'component_name': 'iframe', 'config': {'url': 'http://192.168.1.1'}, 'icon': 'mdi:network-wireless', @@ -64,7 +62,7 @@ class TestPanelIframe(unittest.TestCase): 'url_path': 'router' } - assert self.hass.data[frontend.DATA_PANELS]['weather'] == { + assert self.hass.data[frontend.DATA_PANELS].get('weather') == { 'component_name': 'iframe', 'config': {'url': 'https://www.wunderground.com/us/ca/san-diego'}, 'icon': 'mdi:weather', From ba019c799a5807049e5143da3b6a0645131eae7e Mon Sep 17 00:00:00 2001 From: Martin Hjelmare Date: Fri, 14 Jul 2017 04:26:21 +0200 Subject: [PATCH 002/118] Make deps directory persistent over upgrades (#7801) * Use pip install --user if venv not active * Set PYTHONUSERBASE to deps directory, when installing with --user option. * Reset --prefix option to workaround incompatability when installing with --user option. This requires pip version 8.0.0 or greater. * Require pip version 8.0.3. * Do not delete deps directory on home assistant upgrade. * Fix local lib mount and check package exist. * Update and add tests * Fix upgrade from before version 0.46 * Extract function to get user site * Add function(s) to package util to get user site. * Use async subprocess for one of the functions to get user site. * Add function to package util to check if virtual environment is active. * Add and update tests. * Update version for last removal of deps dir * Address comments * Rewrite package util tests with pytest * Rewrite all existing unittest class based tests for package util as test functions, and capitalize pytest fixtures. * Add test for installing with target inside venv. --- homeassistant/bootstrap.py | 24 +- homeassistant/config.py | 10 +- homeassistant/package_constraints.txt | 2 +- homeassistant/scripts/__init__.py | 12 +- homeassistant/setup.py | 4 + homeassistant/util/package.py | 70 ++++-- requirements_all.txt | 2 +- setup.py | 2 +- tests/test_config.py | 52 +++-- tests/test_setup.py | 37 ++- tests/util/test_package.py | 316 ++++++++++++++++---------- 11 files changed, 364 insertions(+), 167 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 5f64fd447a6..a90a96e4fa0 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -19,6 +19,7 @@ from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE from homeassistant.setup import async_setup_component import homeassistant.loader as loader from homeassistant.util.logging import AsyncHandler +from homeassistant.util.package import async_get_user_site, get_user_site from homeassistant.util.yaml import clear_secret_cache from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.signal import async_register_signal_handling @@ -48,7 +49,8 @@ def from_config_dict(config: Dict[str, Any], if config_dir is not None: config_dir = os.path.abspath(config_dir) hass.config.config_dir = config_dir - mount_local_lib_path(config_dir) + hass.loop.run_until_complete( + async_mount_local_lib_path(config_dir, hass.loop)) # run task hass = hass.loop.run_until_complete( @@ -183,7 +185,7 @@ def async_from_config_file(config_path: str, # Set config dir to directory holding config file config_dir = os.path.abspath(os.path.dirname(config_path)) hass.config.config_dir = config_dir - yield from hass.async_add_job(mount_local_lib_path, config_dir) + yield from async_mount_local_lib_path(config_dir, hass.loop) async_enable_logging(hass, verbose, log_rotate_days) @@ -276,11 +278,23 @@ def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False, def mount_local_lib_path(config_dir: str) -> str: + """Add local library to Python Path.""" + deps_dir = os.path.join(config_dir, 'deps') + lib_dir = get_user_site(deps_dir) + if lib_dir not in sys.path: + sys.path.insert(0, lib_dir) + return deps_dir + + +@asyncio.coroutine +def async_mount_local_lib_path(config_dir: str, + loop: asyncio.AbstractEventLoop) -> str: """Add local library to Python Path. - Async friendly. + This function is a coroutine. """ deps_dir = os.path.join(config_dir, 'deps') - if deps_dir not in sys.path: - sys.path.insert(0, os.path.join(config_dir, 'deps')) + lib_dir = yield from async_get_user_site(deps_dir, loop=loop) + if lib_dir not in sys.path: + sys.path.insert(0, lib_dir) return deps_dir diff --git a/homeassistant/config.py b/homeassistant/config.py index d91854c5162..cb8d0b442c1 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -1,6 +1,8 @@ """Module to help with parsing and generating configuration files.""" import asyncio from collections import OrderedDict +# pylint: disable=no-name-in-module +from distutils.version import LooseVersion # pylint: disable=import-error import logging import os import re @@ -295,9 +297,11 @@ def process_ha_config_upgrade(hass): _LOGGER.info('Upgrading config directory from %s to %s', conf_version, __version__) - lib_path = hass.config.path('deps') - if os.path.isdir(lib_path): - shutil.rmtree(lib_path) + if LooseVersion(conf_version) < LooseVersion('0.49'): + # 0.49 introduced persistent deps dir. + lib_path = hass.config.path('deps') + if os.path.isdir(lib_path): + shutil.rmtree(lib_path) with open(version_path, 'wt') as outp: outp.write(__version__) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 1de3671a296..9414bc98dc8 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -1,7 +1,7 @@ requests==2.14.2 pyyaml>=3.11,<4 pytz>=2017.02 -pip>=7.1.0 +pip>=8.0.3 jinja2>=2.9.5 voluptuous==0.10.5 typing>=3,<4 diff --git a/homeassistant/scripts/__init__.py b/homeassistant/scripts/__init__.py index af9e00626dd..2324613acfb 100644 --- a/homeassistant/scripts/__init__.py +++ b/homeassistant/scripts/__init__.py @@ -7,7 +7,8 @@ import logging from typing import List from homeassistant.config import get_default_config_dir -from homeassistant.util.package import install_package +from homeassistant.const import CONSTRAINT_FILE +from homeassistant.util.package import install_package, is_virtual_env from homeassistant.bootstrap import mount_local_lib_path @@ -40,7 +41,14 @@ def run(args: List) -> int: logging.basicConfig(stream=sys.stdout, level=logging.INFO) for req in getattr(script, 'REQUIREMENTS', []): - if not install_package(req, target=deps_dir): + if is_virtual_env(): + returncode = install_package(req, constraints=os.path.join( + os.path.dirname(__file__), os.pardir, CONSTRAINT_FILE)) + else: + returncode = install_package( + req, target=deps_dir, constraints=os.path.join( + os.path.dirname(__file__), os.pardir, CONSTRAINT_FILE)) + if not returncode: print('Aborting scipt, could not install dependency', req) return 1 diff --git a/homeassistant/setup.py b/homeassistant/setup.py index 285a5755145..3594399281f 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -77,6 +77,10 @@ def _async_process_requirements(hass: core.HomeAssistant, name: str, def pip_install(mod): """Install packages.""" + if pkg_util.is_virtual_env(): + return pkg_util.install_package( + mod, constraints=os.path.join( + os.path.dirname(__file__), CONSTRAINT_FILE)) return pkg_util.install_package( mod, target=hass.config.path('deps'), constraints=os.path.join( diff --git a/homeassistant/util/package.py b/homeassistant/util/package.py index a5a863b0880..4736c1acc1a 100644 --- a/homeassistant/util/package.py +++ b/homeassistant/util/package.py @@ -1,4 +1,5 @@ """Helpers to install PyPi packages.""" +import asyncio import logging import os import sys @@ -24,20 +25,26 @@ def install_package(package: str, upgrade: bool=True, """ # Not using 'import pip; pip.main([])' because it breaks the logger with INSTALL_LOCK: - if check_package_exists(package, target): + if check_package_exists(package): return True - _LOGGER.info("Attempting install of %s", package) + _LOGGER.info('Attempting install of %s', package) + env = os.environ.copy() args = [sys.executable, '-m', 'pip', 'install', '--quiet', package] if upgrade: args.append('--upgrade') - if target: - args += ['--target', os.path.abspath(target)] - if constraints is not None: args += ['--constraint', constraints] - - process = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) + if target: + assert not is_virtual_env() + # This only works if not running in venv + args += ['--user'] + env['PYTHONUSERBASE'] = os.path.abspath(target) + if sys.platform != 'win32': + # Workaround for incompatible prefix setting + # See http://stackoverflow.com/a/4495175 + args += ['--prefix='] + process = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) _, stderr = process.communicate() if process.returncode != 0: _LOGGER.error("Unable to install package %s: %s", @@ -47,7 +54,7 @@ def install_package(package: str, upgrade: bool=True, return True -def check_package_exists(package: str, lib_dir: str) -> bool: +def check_package_exists(package: str) -> bool: """Check if a package is installed globally or in lib_dir. Returns True when the requirement is met. @@ -59,12 +66,43 @@ def check_package_exists(package: str, lib_dir: str) -> bool: # This is a zip file req = pkg_resources.Requirement.parse(urlparse(package).fragment) - # Check packages from lib dir - if lib_dir is not None: - if any(dist in req for dist in - pkg_resources.find_distributions(lib_dir)): - return True + env = pkg_resources.Environment() + return any(dist in req for dist in env[req.project_name]) - # Check packages from global + virtual environment - # pylint: disable=not-an-iterable - return any(dist in req for dist in pkg_resources.working_set) + +def is_virtual_env() -> bool: + """Return true if environment is a virtual environment.""" + return hasattr(sys, 'real_prefix') + + +def _get_user_site(deps_dir: str) -> tuple: + """Get arguments and environment for subprocess used in get_user_site.""" + env = os.environ.copy() + env['PYTHONUSERBASE'] = os.path.abspath(deps_dir) + args = [sys.executable, '-m', 'site', '--user-site'] + return args, env + + +def get_user_site(deps_dir: str) -> str: + """Return user local library path.""" + args, env = _get_user_site(deps_dir) + process = Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) + stdout, _ = process.communicate() + lib_dir = stdout.decode().strip() + return lib_dir + + +@asyncio.coroutine +def async_get_user_site(deps_dir: str, loop: asyncio.AbstractEventLoop) -> str: + """Return user local library path. + + This function is a coroutine. + """ + args, env = _get_user_site(deps_dir) + process = yield from asyncio.create_subprocess_exec( + *args, loop=loop, stdin=asyncio.subprocess.PIPE, + stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.DEVNULL, + env=env) + stdout, _ = yield from process.communicate() + lib_dir = stdout.decode().strip() + return lib_dir diff --git a/requirements_all.txt b/requirements_all.txt index d4e4a30add7..60d25a41049 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2,7 +2,7 @@ requests==2.14.2 pyyaml>=3.11,<4 pytz>=2017.02 -pip>=7.1.0 +pip>=8.0.3 jinja2>=2.9.5 voluptuous==0.10.5 typing>=3,<4 diff --git a/setup.py b/setup.py index 4476bc2f9f0..d19a074889a 100755 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ REQUIRES = [ 'requests==2.14.2', 'pyyaml>=3.11,<4', 'pytz>=2017.02', - 'pip>=7.1.0', + 'pip>=8.0.3', 'jinja2>=2.9.5', 'voluptuous==0.10.5', 'typing>=3,<4', diff --git a/tests/test_config.py b/tests/test_config.py index 00b631a2f78..eba98795fe9 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -260,40 +260,30 @@ class TestConfig(unittest.TestCase): @mock.patch('homeassistant.config.shutil') @mock.patch('homeassistant.config.os') def test_remove_lib_on_upgrade(self, mock_os, mock_shutil): - """Test removal of library on upgrade.""" - ha_version = '0.7.0' - + """Test removal of library on upgrade from before 0.49.""" + ha_version = '0.48.0' mock_os.path.isdir = mock.Mock(return_value=True) - mock_open = mock.mock_open() with mock.patch('homeassistant.config.open', mock_open, create=True): opened_file = mock_open.return_value # pylint: disable=no-member opened_file.readline.return_value = ha_version - self.hass.config.path = mock.Mock() - config_util.process_ha_config_upgrade(self.hass) - hass_path = self.hass.config.path.return_value self.assertEqual(mock_os.path.isdir.call_count, 1) self.assertEqual( mock_os.path.isdir.call_args, mock.call(hass_path) ) - self.assertEqual(mock_shutil.rmtree.call_count, 1) self.assertEqual( mock_shutil.rmtree.call_args, mock.call(hass_path) ) - @mock.patch('homeassistant.config.shutil') - @mock.patch('homeassistant.config.os') - def test_not_remove_lib_if_not_upgrade(self, mock_os, mock_shutil): - """Test removal of library with no upgrade.""" - ha_version = __version__ - - mock_os.path.isdir = mock.Mock(return_value=True) + def test_process_config_upgrade(self): + """Test update of version on upgrade.""" + ha_version = '0.8.0' mock_open = mock.mock_open() with mock.patch('homeassistant.config.open', mock_open, create=True): @@ -301,12 +291,38 @@ class TestConfig(unittest.TestCase): # pylint: disable=no-member opened_file.readline.return_value = ha_version - self.hass.config.path = mock.Mock() + config_util.process_ha_config_upgrade(self.hass) + + self.assertEqual(opened_file.write.call_count, 1) + self.assertEqual( + opened_file.write.call_args, mock.call(__version__) + ) + + def test_config_upgrade_same_version(self): + """Test no update of version on no upgrade.""" + ha_version = __version__ + + mock_open = mock.mock_open() + with mock.patch('homeassistant.config.open', mock_open, create=True): + opened_file = mock_open.return_value + # pylint: disable=no-member + opened_file.readline.return_value = ha_version config_util.process_ha_config_upgrade(self.hass) - assert mock_os.path.isdir.call_count == 0 - assert mock_shutil.rmtree.call_count == 0 + assert opened_file.write.call_count == 0 + + def test_config_upgrade_no_file(self): + """Test update of version on upgrade, with no version file.""" + mock_open = mock.mock_open() + mock_open.side_effect = [FileNotFoundError(), mock.DEFAULT] + with mock.patch('homeassistant.config.open', mock_open, create=True): + opened_file = mock_open.return_value + # pylint: disable=no-member + config_util.process_ha_config_upgrade(self.hass) + self.assertEqual(opened_file.write.call_count, 1) + self.assertEqual( + opened_file.write.call_args, mock.call(__version__)) @mock.patch('homeassistant.config.shutil') @mock.patch('homeassistant.config.os') diff --git a/tests/test_setup.py b/tests/test_setup.py index 291dfdd741f..742df86242f 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -9,7 +9,7 @@ import logging import voluptuous as vol from homeassistant.core import callback -from homeassistant.const import EVENT_HOMEASSISTANT_START +from homeassistant.const import EVENT_HOMEASSISTANT_START, CONSTRAINT_FILE import homeassistant.config as config_util from homeassistant import setup, loader import homeassistant.util.dt as dt_util @@ -203,6 +203,41 @@ class TestSetup: assert not setup.setup_component(self.hass, 'comp') assert 'comp' not in self.hass.config.components + @mock.patch('homeassistant.setup.os.path.dirname') + @mock.patch('homeassistant.util.package.sys') + @mock.patch('homeassistant.util.package.install_package', + return_value=True) + def test_requirement_installed_in_venv( + self, mock_install, mock_sys, mock_dirname): + """Test requirement installed in virtual environment.""" + mock_sys.real_prefix = 'pythonpath' + mock_dirname.return_value = 'ha_package_path' + self.hass.config.skip_pip = False + loader.set_component( + 'comp', MockModule('comp', requirements=['package==0.0.1'])) + assert setup.setup_component(self.hass, 'comp') + assert 'comp' in self.hass.config.components + assert mock_install.call_args == mock.call( + 'package==0.0.1', + constraints=os.path.join('ha_package_path', CONSTRAINT_FILE)) + + @mock.patch('homeassistant.setup.os.path.dirname') + @mock.patch('homeassistant.util.package.sys', spec=object()) + @mock.patch('homeassistant.util.package.install_package', + return_value=True) + def test_requirement_installed_in_deps( + self, mock_install, mock_sys, mock_dirname): + """Test requirement installed in deps directory.""" + mock_dirname.return_value = 'ha_package_path' + self.hass.config.skip_pip = False + loader.set_component( + 'comp', MockModule('comp', requirements=['package==0.0.1'])) + assert setup.setup_component(self.hass, 'comp') + assert 'comp' in self.hass.config.components + assert mock_install.call_args == mock.call( + 'package==0.0.1', target=self.hass.config.path('deps'), + constraints=os.path.join('ha_package_path', CONSTRAINT_FILE)) + def test_component_not_setup_twice_if_loaded_during_other_setup(self): """Test component setup while waiting for lock is not setup twice.""" result = [] diff --git a/tests/util/test_package.py b/tests/util/test_package.py index e0682d79f57..7ca1315c2e1 100644 --- a/tests/util/test_package.py +++ b/tests/util/test_package.py @@ -1,11 +1,13 @@ """Test Home Assistant package util methods.""" +import asyncio +import logging import os -import pkg_resources -import unittest - +import sys from subprocess import PIPE -from distutils.sysconfig import get_python_lib -from unittest.mock import call, patch, Mock +from unittest.mock import MagicMock, call, patch + +import pkg_resources +import pytest import homeassistant.util.package as package @@ -18,124 +20,200 @@ TEST_ZIP_REQ = 'file://{}#{}' \ .format(os.path.join(RESOURCE_DIR, 'pyhelloworld3.zip'), TEST_NEW_REQ) -@patch('homeassistant.util.package.Popen') -@patch('homeassistant.util.package.check_package_exists') -class TestPackageUtilInstallPackage(unittest.TestCase): - """Test for homeassistant.util.package module.""" - - def setUp(self): - """Setup the tests.""" - self.mock_process = Mock() - self.mock_process.communicate.return_value = (b'message', b'error') - self.mock_process.returncode = 0 - - def test_install_existing_package(self, mock_exists, mock_popen): - """Test an install attempt on an existing package.""" - mock_popen.return_value = self.mock_process - mock_exists.return_value = True - - self.assertTrue(package.install_package(TEST_EXIST_REQ)) - - self.assertEqual(mock_exists.call_count, 1) - self.assertEqual(mock_exists.call_args, call(TEST_EXIST_REQ, None)) - - self.assertEqual(self.mock_process.communicate.call_count, 0) - - @patch('homeassistant.util.package.sys') - def test_install(self, mock_sys, mock_exists, mock_popen): - """Test an install attempt on a package that doesn't exist.""" - mock_exists.return_value = False - mock_popen.return_value = self.mock_process - - self.assertTrue(package.install_package(TEST_NEW_REQ, False)) - - self.assertEqual(mock_exists.call_count, 1) - - self.assertEqual(self.mock_process.communicate.call_count, 1) - self.assertEqual(mock_popen.call_count, 1) - self.assertEqual( - mock_popen.call_args, - call([ - mock_sys.executable, '-m', 'pip', 'install', '--quiet', - TEST_NEW_REQ - ], stdin=PIPE, stdout=PIPE, stderr=PIPE) - ) - - @patch('homeassistant.util.package.sys') - def test_install_upgrade(self, mock_sys, mock_exists, mock_popen): - """Test an upgrade attempt on a package.""" - mock_exists.return_value = False - mock_popen.return_value = self.mock_process - - self.assertTrue(package.install_package(TEST_NEW_REQ)) - - self.assertEqual(mock_exists.call_count, 1) - - self.assertEqual(self.mock_process.communicate.call_count, 1) - self.assertEqual(mock_popen.call_count, 1) - self.assertEqual( - mock_popen.call_args, - call([ - mock_sys.executable, '-m', 'pip', 'install', '--quiet', - TEST_NEW_REQ, '--upgrade' - ], stdin=PIPE, stdout=PIPE, stderr=PIPE) - ) - - @patch('homeassistant.util.package.sys') - def test_install_target(self, mock_sys, mock_exists, mock_popen): - """Test an install with a target.""" - target = 'target_folder' - mock_exists.return_value = False - mock_popen.return_value = self.mock_process - - self.assertTrue( - package.install_package(TEST_NEW_REQ, False, target=target) - ) - - self.assertEqual(mock_exists.call_count, 1) - - self.assertEqual(self.mock_process.communicate.call_count, 1) - self.assertEqual(mock_popen.call_count, 1) - self.assertEqual( - mock_popen.call_args, - call([ - mock_sys.executable, '-m', 'pip', 'install', '--quiet', - TEST_NEW_REQ, '--target', os.path.abspath(target) - ], stdin=PIPE, stdout=PIPE, stderr=PIPE) - ) - - @patch('homeassistant.util.package._LOGGER') - @patch('homeassistant.util.package.sys') - def test_install_error(self, mock_sys, mock_logger, mock_exists, - mock_popen): - """Test an install with a target.""" - mock_exists.return_value = False - mock_popen.return_value = self.mock_process - self.mock_process.returncode = 1 - - self.assertFalse(package.install_package(TEST_NEW_REQ)) - - self.assertEqual(mock_logger.error.call_count, 1) +@pytest.fixture +def mock_sys(): + """Mock sys.""" + with patch('homeassistant.util.package.sys', spec=object) as sys_mock: + sys_mock.executable = 'python3' + yield sys_mock -class TestPackageUtilCheckPackageExists(unittest.TestCase): - """Test for homeassistant.util.package module.""" +@pytest.fixture +def mock_exists(): + """Mock check_package_exists.""" + with patch('homeassistant.util.package.check_package_exists') as mock: + mock.return_value = False + yield mock - def test_check_package_global(self): - """Test for a globally-installed package.""" - installed_package = list(pkg_resources.working_set)[0].project_name - self.assertTrue(package.check_package_exists(installed_package, None)) +@pytest.fixture +def deps_dir(): + """Return path to deps directory.""" + return os.path.abspath('/deps_dir') - def test_check_package_local(self): - """Test for a locally-installed package.""" - lib_dir = get_python_lib() - installed_package = list(pkg_resources.working_set)[0].project_name - self.assertTrue( - package.check_package_exists(installed_package, lib_dir) - ) +@pytest.fixture +def lib_dir(deps_dir): + """Return path to lib directory.""" + return os.path.join(deps_dir, 'lib_dir') - def test_check_package_zip(self): - """Test for an installed zip package.""" - self.assertFalse(package.check_package_exists(TEST_ZIP_REQ, None)) + +@pytest.fixture +def mock_popen(lib_dir): + """Return a Popen mock.""" + with patch('homeassistant.util.package.Popen') as popen_mock: + popen_mock.return_value.communicate.return_value = ( + bytes(lib_dir, 'utf-8'), b'error') + popen_mock.return_value.returncode = 0 + yield popen_mock + + +@pytest.fixture +def mock_env_copy(): + """Mock os.environ.copy.""" + with patch('homeassistant.util.package.os.environ.copy') as env_copy: + env_copy.return_value = {} + yield env_copy + + +@asyncio.coroutine +def mock_async_subprocess(): + """Return an async Popen mock.""" + async_popen = MagicMock() + + @asyncio.coroutine + def communicate(input=None): + """Communicate mock.""" + stdout = bytes('/deps_dir/lib_dir', 'utf-8') + return (stdout, None) + + async_popen.communicate = communicate + return async_popen + + +def test_install_existing_package(mock_exists, mock_popen): + """Test an install attempt on an existing package.""" + mock_exists.return_value = True + assert package.install_package(TEST_EXIST_REQ) + assert mock_exists.call_count == 1 + assert mock_exists.call_args == call(TEST_EXIST_REQ) + assert mock_popen.return_value.communicate.call_count == 0 + + +def test_install(mock_sys, mock_exists, mock_popen, mock_env_copy): + """Test an install attempt on a package that doesn't exist.""" + env = mock_env_copy() + assert package.install_package(TEST_NEW_REQ, False) + assert mock_exists.call_count == 1 + assert mock_popen.call_count == 1 + assert ( + mock_popen.call_args == + call([ + mock_sys.executable, '-m', 'pip', 'install', '--quiet', + TEST_NEW_REQ + ], stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) + ) + assert mock_popen.return_value.communicate.call_count == 1 + + +def test_install_upgrade(mock_sys, mock_exists, mock_popen, mock_env_copy): + """Test an upgrade attempt on a package.""" + env = mock_env_copy() + assert package.install_package(TEST_NEW_REQ) + assert mock_exists.call_count == 1 + assert mock_popen.call_count == 1 + assert ( + mock_popen.call_args == + call([ + mock_sys.executable, '-m', 'pip', 'install', '--quiet', + TEST_NEW_REQ, '--upgrade' + ], stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) + ) + assert mock_popen.return_value.communicate.call_count == 1 + + +def test_install_target(mock_sys, mock_exists, mock_popen, mock_env_copy): + """Test an install with a target.""" + target = 'target_folder' + env = mock_env_copy() + env['PYTHONUSERBASE'] = os.path.abspath(target) + mock_sys.platform = 'linux' + args = [ + mock_sys.executable, '-m', 'pip', 'install', '--quiet', + TEST_NEW_REQ, '--user', '--prefix='] + + assert package.install_package(TEST_NEW_REQ, False, target=target) + assert mock_exists.call_count == 1 + assert mock_popen.call_count == 1 + assert ( + mock_popen.call_args == + call(args, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) + ) + assert mock_popen.return_value.communicate.call_count == 1 + + +def test_install_target_venv(mock_sys, mock_exists, mock_popen, mock_env_copy): + """Test an install with a target in a virtual environment.""" + target = 'target_folder' + mock_sys.real_prefix = '/usr' + with pytest.raises(AssertionError): + package.install_package(TEST_NEW_REQ, False, target=target) + + +def test_install_error(caplog, mock_sys, mock_exists, mock_popen): + """Test an install with a target.""" + caplog.set_level(logging.WARNING) + mock_popen.return_value.returncode = 1 + assert not package.install_package(TEST_NEW_REQ) + assert len(caplog.records) == 1 + for record in caplog.records: + assert record.levelname == 'ERROR' + + +def test_install_constraint(mock_sys, mock_exists, mock_popen, mock_env_copy): + """Test install with constraint file on not installed package.""" + env = mock_env_copy() + constraints = 'constraints_file.txt' + assert package.install_package( + TEST_NEW_REQ, False, constraints=constraints) + assert mock_exists.call_count == 1 + assert mock_popen.call_count == 1 + assert ( + mock_popen.call_args == + call([ + mock_sys.executable, '-m', 'pip', 'install', '--quiet', + TEST_NEW_REQ, '--constraint', constraints + ], stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) + ) + assert mock_popen.return_value.communicate.call_count == 1 + + +def test_check_package_global(): + """Test for an installed package.""" + installed_package = list(pkg_resources.working_set)[0].project_name + assert package.check_package_exists(installed_package) + + +def test_check_package_zip(): + """Test for an installed zip package.""" + assert not package.check_package_exists(TEST_ZIP_REQ) + + +def test_get_user_site(deps_dir, lib_dir, mock_popen, mock_env_copy): + """Test get user site directory.""" + env = mock_env_copy() + env['PYTHONUSERBASE'] = os.path.abspath(deps_dir) + args = [sys.executable, '-m', 'site', '--user-site'] + ret = package.get_user_site(deps_dir) + assert mock_popen.call_count == 1 + assert mock_popen.call_args == call( + args, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) + assert ret == lib_dir + + +@asyncio.coroutine +def test_async_get_user_site(hass, mock_env_copy): + """Test async get user site directory.""" + deps_dir = '/deps_dir' + env = mock_env_copy() + env['PYTHONUSERBASE'] = os.path.abspath(deps_dir) + args = [sys.executable, '-m', 'site', '--user-site'] + with patch('homeassistant.util.package.asyncio.create_subprocess_exec', + return_value=mock_async_subprocess()) as popen_mock: + ret = yield from package.async_get_user_site(deps_dir, hass.loop) + assert popen_mock.call_count == 1 + assert popen_mock.call_args == call( + *args, loop=hass.loop, stdin=asyncio.subprocess.PIPE, + stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.DEVNULL, + env=env) + assert ret == os.path.join(deps_dir, 'lib_dir') From 4fde0ffe9c1aa246ca4689aa9b239a991c012448 Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Fri, 14 Jul 2017 04:38:36 +0200 Subject: [PATCH 003/118] LIFX: support for multizone (#8399) * Make aiolifx modules easily available * Use aiolifx features_map for deciding bulb features Also move the feature detection out of Light so it is available even during the initial detection. * Move each LIFX light type to a separate class * Simplify AwaitAioLIFX This has become possible with recent aiolifx that calls the callback even when a message is lost. Now the wrapper can be used also before a Light is added though the register callback then has to become a coroutine. * Refactor send_color * Add support for multizone This lets lifx_set_state work on individual zones. Also update to aiolifx_effects 0.1.1 that restores the state for individual zones. --- homeassistant/components/light/lifx.py | 269 ++++++++++++------- homeassistant/components/light/services.yaml | 4 + requirements_all.txt | 2 +- 3 files changed, 181 insertions(+), 94 deletions(-) diff --git a/homeassistant/components/light/lifx.py b/homeassistant/components/light/lifx.py index 0c5535ea8ea..a32aa0c4a6b 100644 --- a/homeassistant/components/light/lifx.py +++ b/homeassistant/components/light/lifx.py @@ -33,7 +33,7 @@ import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) -REQUIREMENTS = ['aiolifx==0.5.2', 'aiolifx_effects==0.1.0'] +REQUIREMENTS = ['aiolifx==0.5.2', 'aiolifx_effects==0.1.1'] UDP_BROADCAST_PORT = 56700 @@ -53,10 +53,12 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ SERVICE_LIFX_SET_STATE = 'lifx_set_state' ATTR_INFRARED = 'infrared' +ATTR_ZONES = 'zones' ATTR_POWER = 'power' LIFX_SET_STATE_SCHEMA = LIGHT_TURN_ON_SCHEMA.extend({ ATTR_INFRARED: vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255)), + ATTR_ZONES: vol.All(cv.ensure_list, [cv.positive_int]), ATTR_POWER: cv.boolean, }) @@ -112,11 +114,21 @@ LIFX_EFFECT_STOP_SCHEMA = vol.Schema({ }) +def aiolifx(): + """Return the aiolifx module.""" + import aiolifx as aiolifx_module + return aiolifx_module + + +def aiolifx_effects(): + """Return the aiolifx_effects module.""" + import aiolifx_effects as aiolifx_effects_module + return aiolifx_effects_module + + @asyncio.coroutine def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the LIFX platform.""" - import aiolifx - if sys.platform == 'win32': _LOGGER.warning("The lifx platform is known to not work on Windows. " "Consider using the lifx_legacy platform instead") @@ -124,7 +136,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): server_addr = config.get(CONF_SERVER) lifx_manager = LIFXManager(hass, async_add_devices) - lifx_discovery = aiolifx.LifxDiscovery( + lifx_discovery = aiolifx().LifxDiscovery( hass.loop, lifx_manager, discovery_interval=DISCOVERY_INTERVAL, @@ -145,6 +157,16 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): return True +def lifxwhite(device): + """Return whether this is a white-only bulb.""" + return not aiolifx().products.features_map[device.product]["color"] + + +def lifxmultizone(device): + """Return whether this is a multizone bulb/strip.""" + return aiolifx().products.features_map[device.product]["multizone"] + + def find_hsbk(**kwargs): """Find the desired color from a number of possible inputs.""" hue, saturation, brightness, kelvin = [None]*4 @@ -187,11 +209,10 @@ class LIFXManager(object): def __init__(self, hass, async_add_devices): """Initialize the light.""" - import aiolifx_effects self.entities = {} self.hass = hass self.async_add_devices = async_add_devices - self.effects_conductor = aiolifx_effects.Conductor(loop=hass.loop) + self.effects_conductor = aiolifx_effects().Conductor(loop=hass.loop) descriptions = load_yaml_config_file( path.join(path.dirname(__file__), 'services.yaml')) @@ -245,11 +266,10 @@ class LIFXManager(object): @asyncio.coroutine def start_effect(self, entities, service, **kwargs): """Start a light effect on entities.""" - import aiolifx_effects devices = list(map(lambda l: l.device, entities)) if service == SERVICE_EFFECT_PULSE: - effect = aiolifx_effects.EffectPulse( + effect = aiolifx_effects().EffectPulse( power_on=kwargs.get(ATTR_POWER_ON), period=kwargs.get(ATTR_PERIOD), cycles=kwargs.get(ATTR_CYCLES), @@ -264,7 +284,7 @@ class LIFXManager(object): if ATTR_BRIGHTNESS in kwargs: brightness = convert_8_to_16(kwargs[ATTR_BRIGHTNESS]) - effect = aiolifx_effects.EffectColorloop( + effect = aiolifx_effects().EffectColorloop( power_on=kwargs.get(ATTR_POWER_ON), period=kwargs.get(ATTR_PERIOD), change=kwargs.get(ATTR_CHANGE), @@ -289,32 +309,39 @@ class LIFXManager(object): @callback def register(self, device): - """Handle for newly detected bulb.""" + """Handler for newly detected bulb.""" + self.hass.async_add_job(self.async_register(device)) + + @asyncio.coroutine + def async_register(self, device): + """Handler for newly detected bulb.""" if device.mac_addr in self.entities: entity = self.entities[device.mac_addr] - entity.device = device entity.registered = True _LOGGER.debug("%s register AGAIN", entity.who) - self.hass.async_add_job(entity.async_update_ha_state()) + yield from entity.async_update() + yield from entity.async_update_ha_state() else: _LOGGER.debug("%s register NEW", device.ip_addr) device.timeout = MESSAGE_TIMEOUT device.retry_count = MESSAGE_RETRIES device.unregister_timeout = UNAVAILABLE_GRACE - device.get_version(self.got_version) - @callback - def got_version(self, device, msg): - """Request current color setting once we have the product version.""" - device.get_color(self.ready) + ack = AwaitAioLIFX().wait + yield from ack(device.get_version) + yield from ack(device.get_color) - @callback - def ready(self, device, msg): - """Handle the device once all data is retrieved.""" - entity = LIFXLight(device, self.effects_conductor) - _LOGGER.debug("%s register READY", entity.who) - self.entities[device.mac_addr] = entity - self.async_add_devices([entity]) + if lifxwhite(device): + entity = LIFXWhite(device, self.effects_conductor) + elif lifxmultizone(device): + yield from ack(partial(device.get_color_zones, start_index=0)) + entity = LIFXStrip(device, self.effects_conductor) + else: + entity = LIFXColor(device, self.effects_conductor) + + _LOGGER.debug("%s register READY", entity.who) + self.entities[device.mac_addr] = entity + self.async_add_devices([entity]) @callback def unregister(self, device): @@ -329,9 +356,8 @@ class LIFXManager(object): class AwaitAioLIFX: """Wait for an aiolifx callback and return the message.""" - def __init__(self, light): + def __init__(self): """Initialize the wrapper.""" - self.light = light self.device = None self.message = None self.event = asyncio.Event() @@ -373,15 +399,8 @@ class LIFXLight(Light): self.device = device self.effects_conductor = effects_conductor self.registered = True - self.product = device.product self.postponed_update = None - @property - def lifxwhite(self): - """Return whether this is a white-only bulb.""" - # https://lan.developer.lifx.com/docs/lifx-products - return self.product in [10, 11, 18] - @property def available(self): """Return the availability of the device.""" @@ -397,14 +416,6 @@ class LIFXLight(Light): """Return a string identifying the device.""" return "%s (%s)" % (self.device.ip_addr, self.name) - @property - def rgb_color(self): - """Return the RGB value.""" - hue, sat, bri, _ = self.device.color - - return color_util.color_hsv_to_RGB( - hue, convert_16_to_8(sat), convert_16_to_8(bri)) - @property def brightness(self): """Return the brightness of this light between 0..255.""" @@ -421,26 +432,6 @@ class LIFXLight(Light): _LOGGER.debug("color_temp: %d", temperature) return temperature - @property - def min_mireds(self): - """Return the coldest color_temp that this light supports.""" - # The 3 LIFX "White" products supported a limited temperature range - if self.lifxwhite: - kelvin = 6500 - else: - kelvin = 9000 - return math.floor(color_util.color_temperature_kelvin_to_mired(kelvin)) - - @property - def max_mireds(self): - """Return the warmest color_temp that this light supports.""" - # The 3 LIFX "White" products supported a limited temperature range - if self.lifxwhite: - kelvin = 2700 - else: - kelvin = 2500 - return math.ceil(color_util.color_temperature_kelvin_to_mired(kelvin)) - @property def is_on(self): """Return true if device is on.""" @@ -454,32 +445,6 @@ class LIFXLight(Light): return 'lifx_effect_' + effect.name return None - @property - def supported_features(self): - """Flag supported features.""" - features = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | - SUPPORT_TRANSITION | SUPPORT_EFFECT) - - if not self.lifxwhite: - features |= SUPPORT_RGB_COLOR | SUPPORT_XY_COLOR - - return features - - @property - def effect_list(self): - """Return the list of supported effects for this light.""" - if self.lifxwhite: - return [ - SERVICE_EFFECT_PULSE, - SERVICE_EFFECT_STOP, - ] - - return [ - SERVICE_EFFECT_COLORLOOP, - SERVICE_EFFECT_PULSE, - SERVICE_EFFECT_STOP, - ] - @asyncio.coroutine def update_after_transition(self, now): """Request new status after completion of the last transition.""" @@ -530,30 +495,36 @@ class LIFXLight(Light): power_on = kwargs.get(ATTR_POWER, False) power_off = not kwargs.get(ATTR_POWER, True) - hsbk = merge_hsbk(self.device.color, find_hsbk(**kwargs)) + hsbk = find_hsbk(**kwargs) # Send messages, waiting for ACK each time - ack = AwaitAioLIFX(self).wait + ack = AwaitAioLIFX().wait bulb = self.device if not self.is_on: if power_off: yield from ack(partial(bulb.set_power, False)) if hsbk: - yield from ack(partial(bulb.set_color, hsbk)) + yield from self.send_color(ack, hsbk, kwargs, duration=0) if power_on: yield from ack(partial(bulb.set_power, True, duration=fade)) else: if power_on: yield from ack(partial(bulb.set_power, True)) if hsbk: - yield from ack(partial(bulb.set_color, hsbk, duration=fade)) + yield from self.send_color(ack, hsbk, kwargs, duration=fade) if power_off: yield from ack(partial(bulb.set_power, False, duration=fade)) # Schedule an update when the transition is complete self.update_later(fade) + @asyncio.coroutine + def send_color(self, ack, hsbk, kwargs, duration): + """Send a color change to the device.""" + hsbk = merge_hsbk(self.device.color, hsbk) + yield from ack(partial(self.device.set_color, hsbk, duration=duration)) + @asyncio.coroutine def default_effect(self, **kwargs): """Start an effect with default parameters.""" @@ -569,5 +540,117 @@ class LIFXLight(Light): _LOGGER.debug("%s async_update", self.who) if self.available: # Avoid state ping-pong by holding off updates as the state settles - yield from asyncio.sleep(0.25) - yield from AwaitAioLIFX(self).wait(self.device.get_color) + yield from asyncio.sleep(0.3) + yield from AwaitAioLIFX().wait(self.device.get_color) + + +class LIFXWhite(LIFXLight): + """Representation of a white-only LIFX light.""" + + @property + def min_mireds(self): + """Return the coldest color_temp that this light supports.""" + return math.floor(color_util.color_temperature_kelvin_to_mired(6500)) + + @property + def max_mireds(self): + """Return the warmest color_temp that this light supports.""" + return math.ceil(color_util.color_temperature_kelvin_to_mired(2700)) + + @property + def supported_features(self): + """Flag supported features.""" + return (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_TRANSITION | + SUPPORT_EFFECT) + + @property + def effect_list(self): + """Return the list of supported effects for this light.""" + return [ + SERVICE_EFFECT_PULSE, + SERVICE_EFFECT_STOP, + ] + + +class LIFXColor(LIFXLight): + """Representation of a color LIFX light.""" + + @property + def min_mireds(self): + """Return the coldest color_temp that this light supports.""" + return math.floor(color_util.color_temperature_kelvin_to_mired(9000)) + + @property + def max_mireds(self): + """Return the warmest color_temp that this light supports.""" + return math.ceil(color_util.color_temperature_kelvin_to_mired(2500)) + + @property + def supported_features(self): + """Flag supported features.""" + return (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_TRANSITION | + SUPPORT_EFFECT | SUPPORT_RGB_COLOR | SUPPORT_XY_COLOR) + + @property + def effect_list(self): + """Return the list of supported effects for this light.""" + return [ + SERVICE_EFFECT_COLORLOOP, + SERVICE_EFFECT_PULSE, + SERVICE_EFFECT_STOP, + ] + + @property + def rgb_color(self): + """Return the RGB value.""" + hue, sat, bri, _ = self.device.color + + return color_util.color_hsv_to_RGB( + hue, convert_16_to_8(sat), convert_16_to_8(bri)) + + +class LIFXStrip(LIFXColor): + """Representation of a LIFX light strip with multiple zones.""" + + @asyncio.coroutine + def send_color(self, ack, hsbk, kwargs, duration): + """Send a color change to the device.""" + bulb = self.device + num_zones = len(bulb.color_zones) + + # Zone brightness is not reported when powered off + if not self.is_on and hsbk[2] is None: + yield from ack(partial(bulb.set_power, True)) + yield from self.async_update() + yield from ack(partial(bulb.set_power, False)) + + zones = kwargs.get(ATTR_ZONES, None) + if zones is None: + zones = list(range(0, num_zones)) + else: + zones = list(filter(lambda x: x < num_zones, set(zones))) + + # Send new color to each zone + for index, zone in enumerate(zones): + zone_hsbk = merge_hsbk(bulb.color_zones[zone], hsbk) + apply = 1 if (index == len(zones)-1) else 0 + set_zone = partial(bulb.set_color_zones, + start_index=zone, + end_index=zone, + color=zone_hsbk, + duration=duration, + apply=apply) + yield from ack(set_zone) + + @asyncio.coroutine + def async_update(self): + """Update strip status.""" + if self.available: + yield from super().async_update() + + ack = AwaitAioLIFX().wait + bulb = self.device + + # Each get_color_zones returns the next 8 zones + for zone in range(0, len(bulb.color_zones), 8): + yield from ack(partial(bulb.get_color_zones, start_index=zone)) diff --git a/homeassistant/components/light/services.yaml b/homeassistant/components/light/services.yaml index ef99f18fb42..782d4496442 100644 --- a/homeassistant/components/light/services.yaml +++ b/homeassistant/components/light/services.yaml @@ -117,6 +117,10 @@ lifx_set_state: description: Automatic infrared level (0..255) when light brightness is low example: 255 + zones: + description: List of zone numbers to affect (8 per LIFX Z, starts at 0) + example: '[0,5]' + transition: description: Duration in seconds it takes to get to the final state example: 10 diff --git a/requirements_all.txt b/requirements_all.txt index 60d25a41049..86258306da2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -52,7 +52,7 @@ aiohttp_cors==0.5.3 aiolifx==0.5.2 # homeassistant.components.light.lifx -aiolifx_effects==0.1.0 +aiolifx_effects==0.1.1 # homeassistant.components.scene.hunterdouglas_powerview aiopvapi==1.4 From d8abef9210d63b91b8e55d37bfffe2d96edf0fab Mon Sep 17 00:00:00 2001 From: Dougal Matthews Date: Fri, 14 Jul 2017 04:53:19 +0200 Subject: [PATCH 004/118] Add RGB support to switch.flux (#8417) --- homeassistant/components/switch/flux.py | 20 +++++++++-- tests/components/switch/test_flux.py | 47 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/switch/flux.py b/homeassistant/components/switch/flux.py index daa4d1f8cd1..dea4285e3a9 100644 --- a/homeassistant/components/switch/flux.py +++ b/homeassistant/components/switch/flux.py @@ -37,6 +37,7 @@ CONF_MODE = 'mode' MODE_XY = 'xy' MODE_MIRED = 'mired' +MODE_RGB = 'rgb' DEFAULT_MODE = MODE_XY PLATFORM_SCHEMA = vol.Schema({ @@ -55,7 +56,7 @@ PLATFORM_SCHEMA = vol.Schema({ vol.All(vol.Coerce(int), vol.Range(min=0, max=255)), vol.Optional(CONF_DISABLE_BRIGTNESS_ADJUST): cv.boolean, vol.Optional(CONF_MODE, default=DEFAULT_MODE): - vol.Any(MODE_XY, MODE_MIRED) + vol.Any(MODE_XY, MODE_MIRED, MODE_RGB) }) @@ -79,6 +80,15 @@ def set_lights_temp(hass, lights, mired, brightness): transition=30) +def set_lights_rgb(hass, lights, rgb): + """Set color of array of lights.""" + for light in lights: + if is_on(hass, light): + turn_on(hass, light, + rgb_color=rgb, + transition=30) + + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Flux switches.""" @@ -194,7 +204,8 @@ class FluxSwitch(SwitchDevice): temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset - x_val, y_val, b_val = color_RGB_to_xy(*color_temperature_to_rgb(temp)) + rgb = color_temperature_to_rgb(temp) + x_val, y_val, b_val = color_RGB_to_xy(*rgb) brightness = self._brightness if self._brightness else b_val if self._disable_brightness_adjust: brightness = None @@ -205,6 +216,11 @@ class FluxSwitch(SwitchDevice): "of %s cycle complete at %s", x_val, y_val, brightness, round( percentage_complete * 100), time_state, now) + elif self._mode == MODE_RGB: + set_lights_rgb(self.hass, self._lights, rgb) + _LOGGER.info("Lights updated to rgb:%s, %s%% " + "of %s cycle complete at %s", rgb, + round(percentage_complete * 100), time_state, now) else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) diff --git a/tests/components/switch/test_flux.py b/tests/components/switch/test_flux.py index 2422f0ea334..d529e8c3f56 100644 --- a/tests/components/switch/test_flux.py +++ b/tests/components/switch/test_flux.py @@ -557,3 +557,50 @@ class TestSwitchFlux(unittest.TestCase): self.hass.block_till_done() call = turn_on_calls[-1] self.assertEqual(call.data[light.ATTR_COLOR_TEMP], 269) + + def test_flux_with_rgb(self): + """Test the flux switch´s mode rgb.""" + platform = loader.get_component('light.test') + platform.init() + self.assertTrue( + setup_component(self.hass, light.DOMAIN, + {light.DOMAIN: {CONF_PLATFORM: 'test'}})) + + dev1 = platform.DEVICES[0] + + # Verify initial state of light + state = self.hass.states.get(dev1.entity_id) + self.assertEqual(STATE_ON, state.state) + self.assertIsNone(state.attributes.get('color_temp')) + + test_time = dt_util.now().replace(hour=8, minute=30, second=0) + sunset_time = test_time.replace(hour=17, minute=0, second=0) + sunrise_time = test_time.replace(hour=5, minute=0, second=0) + + def event_date(hass, event, now=None): + if event == 'sunrise': + return sunrise_time + else: + return sunset_time + + with patch('homeassistant.util.dt.now', return_value=test_time): + with patch('homeassistant.helpers.sun.get_astral_event_date', + side_effect=event_date): + assert setup_component(self.hass, switch.DOMAIN, { + switch.DOMAIN: { + 'platform': 'flux', + 'name': 'flux', + 'lights': [dev1.entity_id], + 'mode': 'rgb' + } + }) + turn_on_calls = mock_service( + self.hass, light.DOMAIN, SERVICE_TURN_ON) + switch.turn_on(self.hass, 'switch.flux') + self.hass.block_till_done() + fire_time_changed(self.hass, test_time) + self.hass.block_till_done() + call = turn_on_calls[-1] + rgb = (255, 198, 152) + rounded_call = tuple(map(round, call.data[light.ATTR_RGB_COLOR])) + self.assertEqual(rounded_call, rgb) From 9373d5e9012a77d59f4e782eaf618e6ae0b4be07 Mon Sep 17 00:00:00 2001 From: dersger Date: Fri, 14 Jul 2017 05:00:23 +0200 Subject: [PATCH 005/118] Fix media_position for cast component (#8452) * Make it available during state paused. * Don't adjust for media_position_updated_at. I.e. do as vlc, sonos etc so that returned position is the position at the time of media_position_updated_at, not now. --- homeassistant/components/media_player/cast.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index 418d3576750..51acf68d819 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -234,18 +234,13 @@ class CastDevice(MediaPlayerDevice): @property def media_position(self): """Position of current playing media in seconds.""" - if self.media_status is None or self.media_status_received is None or \ + if self.media_status is None or \ not (self.media_status.player_is_playing or + self.media_status.player_is_paused 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 + return self.media_status.current_time @property def media_position_updated_at(self): From d473f3407bea9e7065704361f9e2edb90f735607 Mon Sep 17 00:00:00 2001 From: Sean Gollschewsky Date: Fri, 14 Jul 2017 04:01:25 +0100 Subject: [PATCH 006/118] Remove km from visibility, add visibility_distance (#8454) * Remove km from visibility, add visibility_distance * Fix line length * Fix trailing space and line break indentation * Indentation * More whitespace --- homeassistant/components/sensor/metoffice.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/metoffice.py b/homeassistant/components/sensor/metoffice.py index a20ec8fdd5a..25516eda5b1 100644 --- a/homeassistant/components/sensor/metoffice.py +++ b/homeassistant/components/sensor/metoffice.py @@ -40,6 +40,15 @@ CONDITION_CLASSES = { 'exceptional': [], } +VISIBILTY_CLASSES = { + 'VP': '<1', + 'PO': '1-4', + 'MO': '4-10', + 'GO': '10-20', + 'VG': '20-40', + 'EX': '>40' +} + SCAN_INTERVAL = timedelta(minutes=35) # Sensor types are defined like: Name, units @@ -51,7 +60,8 @@ SENSOR_TYPES = { 'wind_speed': ['Wind Speed', 'm/s'], 'wind_direction': ['Wind Direction', None], 'wind_gust': ['Wind Gust', 'm/s'], - 'visibility': ['Visibility', 'km'], + 'visibility': ['Visibility', None], + 'visibility_distance': ['Visibility Distance', 'km'], 'uv': ['UV', None], 'precipitation': ['Probability of Precipitation', '%'], 'humidity': ['Humidity', '%'] @@ -119,6 +129,9 @@ class MetOfficeCurrentSensor(Entity): @property def state(self): """Return the state of the sensor.""" + if (self._condition == 'visibility_distance' and + 'visibility' in self.data.data.__dict__.keys()): + return VISIBILTY_CLASSES.get(self.data.data.visibility.value) if self._condition in self.data.data.__dict__.keys(): variable = getattr(self.data.data, self._condition) if self._condition == "weather": From 5829cdfdf191d2b6db67eafaf28c46e92791c2b6 Mon Sep 17 00:00:00 2001 From: Bryce Edwards Date: Thu, 13 Jul 2017 22:02:07 -0500 Subject: [PATCH 007/118] Radarr sensor fix for issue #8250 (#8456) * Radarr sensor fix for issue #8250 * Radarr sensor fix for issue #8250 --- homeassistant/components/sensor/radarr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/radarr.py b/homeassistant/components/sensor/radarr.py index f5efe12c449..59408b4f96b 100644 --- a/homeassistant/components/sensor/radarr.py +++ b/homeassistant/components/sensor/radarr.py @@ -216,9 +216,9 @@ def get_date(zone, offset=0): def get_release_date(data): """Get release date.""" - date = data['physicalRelease'] + date = data.get('physicalRelease') if not date: - date = data['inCinemas'] + date = data.get('inCinemas') return date From 87b83f36023c329b0990d8bae05853aabbe37589 Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Fri, 14 Jul 2017 05:04:23 +0200 Subject: [PATCH 008/118] Accept transition for light.toggle (#8466) --- homeassistant/helpers/entity.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index da177bc4331..49f250c65fa 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -378,18 +378,18 @@ class ToggleEntity(Entity): return self.hass.async_add_job( ft.partial(self.turn_off, **kwargs)) - def toggle(self) -> None: + def toggle(self, **kwargs) -> None: """Toggle the entity.""" if self.is_on: - self.turn_off() + self.turn_off(**kwargs) else: - self.turn_on() + self.turn_on(**kwargs) - def async_toggle(self): + def async_toggle(self, **kwargs): """Toggle the entity. This method must be run in the event loop and returns a coroutine. """ if self.is_on: - return self.async_turn_off() - return self.async_turn_on() + return self.async_turn_off(**kwargs) + return self.async_turn_on(**kwargs) From 6ca828fd146fe1a5b466a030ee501e3c7e19e49f Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 14 Jul 2017 21:26:26 +0300 Subject: [PATCH 009/118] Make themes API work even when themes are not defined. (#8473) --- homeassistant/components/frontend/__init__.py | 11 +++++++---- tests/components/test_frontend.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 4184feabaeb..443ff6f3852 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -212,17 +212,20 @@ def setup(hass, config): register_built_in_panel(hass, panel) themes = config.get(DOMAIN, {}).get(ATTR_THEMES) - if themes: - setup_themes(hass, themes) + setup_themes(hass, themes) return True def setup_themes(hass, themes): """Set up themes data and services.""" - hass.data[DATA_THEMES] = themes - hass.data[DATA_DEFAULT_THEME] = DEFAULT_THEME hass.http.register_view(ThemesView) + hass.data[DATA_DEFAULT_THEME] = DEFAULT_THEME + if themes is None: + hass.data[DATA_THEMES] = {} + return + + hass.data[DATA_THEMES] = themes @callback def update_theme_and_fire_event(): diff --git a/tests/components/test_frontend.py b/tests/components/test_frontend.py index d1e2e5d4346..3682e0a2c14 100644 --- a/tests/components/test_frontend.py +++ b/tests/components/test_frontend.py @@ -133,3 +133,13 @@ def test_themes_reload_themes(hass, mock_http_client_with_themes): json = yield from resp.json() assert json['themes'] == {'sad': {'primary-color': 'blue'}} assert json['default_theme'] == 'default' + + +@asyncio.coroutine +def test_missing_themes(mock_http_client): + """Test that themes API works when themes are not defined.""" + resp = yield from mock_http_client.get('/api/themes') + assert resp.status == 200 + json = yield from resp.json() + assert json['default_theme'] == 'default' + assert json['themes'] == {} From 543e8bb62ed8e8f91d38d486ad2d0cc0727c8ced Mon Sep 17 00:00:00 2001 From: Martin Hjelmare Date: Sat, 15 Jul 2017 16:25:02 +0200 Subject: [PATCH 010/118] Fix check for running inside venv (#8481) * Import and use the function from pip instead of defining it ourselves. * Fix tests. --- homeassistant/scripts/__init__.py | 10 ++++++---- homeassistant/setup.py | 2 +- homeassistant/util/package.py | 10 +++------- tests/test_setup.py | 12 +++++++----- tests/util/test_package.py | 26 +++++++++++++++++++------- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/homeassistant/scripts/__init__.py b/homeassistant/scripts/__init__.py index 2324613acfb..f6934aef8f6 100644 --- a/homeassistant/scripts/__init__.py +++ b/homeassistant/scripts/__init__.py @@ -1,15 +1,17 @@ """Home Assistant command line scripts.""" import argparse import importlib +import logging import os import sys -import logging + from typing import List +from homeassistant.bootstrap import mount_local_lib_path from homeassistant.config import get_default_config_dir from homeassistant.const import CONSTRAINT_FILE -from homeassistant.util.package import install_package, is_virtual_env -from homeassistant.bootstrap import mount_local_lib_path +from homeassistant.util.package import ( + install_package, running_under_virtualenv) def run(args: List) -> int: @@ -41,7 +43,7 @@ def run(args: List) -> int: logging.basicConfig(stream=sys.stdout, level=logging.INFO) for req in getattr(script, 'REQUIREMENTS', []): - if is_virtual_env(): + if running_under_virtualenv(): returncode = install_package(req, constraints=os.path.join( os.path.dirname(__file__), os.pardir, CONSTRAINT_FILE)) else: diff --git a/homeassistant/setup.py b/homeassistant/setup.py index 3594399281f..a7083d010e6 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -77,7 +77,7 @@ def _async_process_requirements(hass: core.HomeAssistant, name: str, def pip_install(mod): """Install packages.""" - if pkg_util.is_virtual_env(): + if pkg_util.running_under_virtualenv(): return pkg_util.install_package( mod, constraints=os.path.join( os.path.dirname(__file__), CONSTRAINT_FILE)) diff --git a/homeassistant/util/package.py b/homeassistant/util/package.py index 4736c1acc1a..a82a50f4e02 100644 --- a/homeassistant/util/package.py +++ b/homeassistant/util/package.py @@ -2,11 +2,12 @@ import asyncio import logging import os +from subprocess import PIPE, Popen import sys import threading -from subprocess import Popen, PIPE from urllib.parse import urlparse +from pip.locations import running_under_virtualenv from typing import Optional import pkg_resources @@ -36,7 +37,7 @@ def install_package(package: str, upgrade: bool=True, if constraints is not None: args += ['--constraint', constraints] if target: - assert not is_virtual_env() + assert not running_under_virtualenv() # This only works if not running in venv args += ['--user'] env['PYTHONUSERBASE'] = os.path.abspath(target) @@ -70,11 +71,6 @@ def check_package_exists(package: str) -> bool: return any(dist in req for dist in env[req.project_name]) -def is_virtual_env() -> bool: - """Return true if environment is a virtual environment.""" - return hasattr(sys, 'real_prefix') - - def _get_user_site(deps_dir: str) -> tuple: """Get arguments and environment for subprocess used in get_user_site.""" env = os.environ.copy() diff --git a/tests/test_setup.py b/tests/test_setup.py index 742df86242f..9a0f85874ad 100644 --- a/tests/test_setup.py +++ b/tests/test_setup.py @@ -204,13 +204,14 @@ class TestSetup: assert 'comp' not in self.hass.config.components @mock.patch('homeassistant.setup.os.path.dirname') - @mock.patch('homeassistant.util.package.sys') + @mock.patch('homeassistant.util.package.running_under_virtualenv', + return_value=True) @mock.patch('homeassistant.util.package.install_package', return_value=True) def test_requirement_installed_in_venv( - self, mock_install, mock_sys, mock_dirname): + self, mock_install, mock_venv, mock_dirname): """Test requirement installed in virtual environment.""" - mock_sys.real_prefix = 'pythonpath' + mock_venv.return_value = True mock_dirname.return_value = 'ha_package_path' self.hass.config.skip_pip = False loader.set_component( @@ -222,11 +223,12 @@ class TestSetup: constraints=os.path.join('ha_package_path', CONSTRAINT_FILE)) @mock.patch('homeassistant.setup.os.path.dirname') - @mock.patch('homeassistant.util.package.sys', spec=object()) + @mock.patch('homeassistant.util.package.running_under_virtualenv', + return_value=False) @mock.patch('homeassistant.util.package.install_package', return_value=True) def test_requirement_installed_in_deps( - self, mock_install, mock_sys, mock_dirname): + self, mock_install, mock_venv, mock_dirname): """Test requirement installed in deps directory.""" mock_dirname.return_value = 'ha_package_path' self.hass.config.skip_pip = False diff --git a/tests/util/test_package.py b/tests/util/test_package.py index 7ca1315c2e1..ade374dad33 100644 --- a/tests/util/test_package.py +++ b/tests/util/test_package.py @@ -66,6 +66,14 @@ def mock_env_copy(): yield env_copy +@pytest.fixture +def mock_venv(): + """Mock homeassistant.util.package.running_under_virtualenv.""" + with patch('homeassistant.util.package.running_under_virtualenv') as mock: + mock.return_value = True + yield mock + + @asyncio.coroutine def mock_async_subprocess(): """Return an async Popen mock.""" @@ -90,7 +98,7 @@ def test_install_existing_package(mock_exists, mock_popen): assert mock_popen.return_value.communicate.call_count == 0 -def test_install(mock_sys, mock_exists, mock_popen, mock_env_copy): +def test_install(mock_sys, mock_exists, mock_popen, mock_env_copy, mock_venv): """Test an install attempt on a package that doesn't exist.""" env = mock_env_copy() assert package.install_package(TEST_NEW_REQ, False) @@ -106,7 +114,8 @@ def test_install(mock_sys, mock_exists, mock_popen, mock_env_copy): assert mock_popen.return_value.communicate.call_count == 1 -def test_install_upgrade(mock_sys, mock_exists, mock_popen, mock_env_copy): +def test_install_upgrade( + mock_sys, mock_exists, mock_popen, mock_env_copy, mock_venv): """Test an upgrade attempt on a package.""" env = mock_env_copy() assert package.install_package(TEST_NEW_REQ) @@ -122,11 +131,13 @@ def test_install_upgrade(mock_sys, mock_exists, mock_popen, mock_env_copy): assert mock_popen.return_value.communicate.call_count == 1 -def test_install_target(mock_sys, mock_exists, mock_popen, mock_env_copy): +def test_install_target( + mock_sys, mock_exists, mock_popen, mock_env_copy, mock_venv): """Test an install with a target.""" target = 'target_folder' env = mock_env_copy() env['PYTHONUSERBASE'] = os.path.abspath(target) + mock_venv.return_value = False mock_sys.platform = 'linux' args = [ mock_sys.executable, '-m', 'pip', 'install', '--quiet', @@ -142,15 +153,15 @@ def test_install_target(mock_sys, mock_exists, mock_popen, mock_env_copy): assert mock_popen.return_value.communicate.call_count == 1 -def test_install_target_venv(mock_sys, mock_exists, mock_popen, mock_env_copy): +def test_install_target_venv( + mock_sys, mock_exists, mock_popen, mock_env_copy, mock_venv): """Test an install with a target in a virtual environment.""" target = 'target_folder' - mock_sys.real_prefix = '/usr' with pytest.raises(AssertionError): package.install_package(TEST_NEW_REQ, False, target=target) -def test_install_error(caplog, mock_sys, mock_exists, mock_popen): +def test_install_error(caplog, mock_sys, mock_exists, mock_popen, mock_venv): """Test an install with a target.""" caplog.set_level(logging.WARNING) mock_popen.return_value.returncode = 1 @@ -160,7 +171,8 @@ def test_install_error(caplog, mock_sys, mock_exists, mock_popen): assert record.levelname == 'ERROR' -def test_install_constraint(mock_sys, mock_exists, mock_popen, mock_env_copy): +def test_install_constraint( + mock_sys, mock_exists, mock_popen, mock_env_copy, mock_venv): """Test install with constraint file on not installed package.""" env = mock_env_copy() constraints = 'constraints_file.txt' From 23b65bfb3044b719d68325dad97a284dbafcd601 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 15 Jul 2017 21:07:15 -0700 Subject: [PATCH 011/118] Version bump to 0.50.0dev0 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index f7df04be7f1..b4b2aac52e3 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ # coding: utf-8 """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 -MINOR_VERSION = 49 +MINOR_VERSION = 50 PATCH_VERSION = '0.dev0' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) From bffa0d2b041531ebe9847a7beb6ae707f6a4e7a8 Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Sun, 16 Jul 2017 13:34:13 +0200 Subject: [PATCH 012/118] Bump to KNXIP 0.5 (#8492) * Bump to KNXIP 0.5 * Updated requirements file --- homeassistant/components/knx.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/knx.py b/homeassistant/components/knx.py index ec533a7850b..9772c19ff78 100644 --- a/homeassistant/components/knx.py +++ b/homeassistant/components/knx.py @@ -13,7 +13,7 @@ from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP, CONF_HOST, CONF_PORT) from homeassistant.helpers.entity import Entity -REQUIREMENTS = ['knxip==0.4'] +REQUIREMENTS = ['knxip==0.5'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 86258306da2..e07cc8de84c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -338,7 +338,7 @@ jsonrpc-websocket==0.5 keyring>=9.3,<10.0 # homeassistant.components.knx -knxip==0.4 +knxip==0.5 # homeassistant.components.device_tracker.owntracks libnacl==1.5.1 From d3be056d1567e5792a4b215ddd0d5eb17c90bfa1 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 16 Jul 2017 09:23:06 -0700 Subject: [PATCH 013/118] Expose all components on hass [Concept] (#8490) * Add components concept * Lint * Raise ImportError if component not found --- homeassistant/components/light/__init__.py | 2 + homeassistant/core.py | 2 + homeassistant/loader.py | 44 ++++++++++++++++++++++ tests/test_loader.py | 32 +++++++++++++++- 4 files changed, 79 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index 1dbd07f9439..5f3caff511a 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -13,6 +13,7 @@ import csv import voluptuous as vol from homeassistant.core import callback +from homeassistant.loader import bind_hass from homeassistant.components import group from homeassistant.config import load_yaml_config_file from homeassistant.const import ( @@ -165,6 +166,7 @@ def turn_on(hass, entity_id=None, transition=None, brightness=None, @callback +@bind_hass def async_turn_on(hass, entity_id=None, transition=None, brightness=None, brightness_pct=None, rgb_color=None, xy_color=None, color_temp=None, kelvin=None, white_value=None, diff --git a/homeassistant/core.py b/homeassistant/core.py index d1779fe420d..496bb018fbd 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -30,6 +30,7 @@ from homeassistant.const import ( EVENT_SERVICE_EXECUTED, EVENT_SERVICE_REGISTERED, EVENT_STATE_CHANGED, EVENT_TIME_CHANGED, MATCH_ALL, EVENT_HOMEASSISTANT_CLOSE, EVENT_SERVICE_REMOVED, __version__) +from homeassistant.loader import Components from homeassistant.exceptions import ( HomeAssistantError, InvalidEntityFormatError) from homeassistant.util.async import ( @@ -128,6 +129,7 @@ class HomeAssistant(object): self.services = ServiceRegistry(self) self.states = StateMachine(self.bus, self.loop) self.config = Config() # type: Config + self.components = Components(self) # This is a dictionary that any component can store any data on. self.data = {} self.state = CoreState.not_running diff --git a/homeassistant/loader.py b/homeassistant/loader.py index 586988a3436..566cdd4fb15 100644 --- a/homeassistant/loader.py +++ b/homeassistant/loader.py @@ -10,6 +10,7 @@ call get_component('switch.your_platform'). In both cases the config directory is checked to see if it contains a user provided version. If not available it will check the built-in components and platforms. """ +import functools as ft import importlib import logging import os @@ -170,6 +171,49 @@ def get_component(comp_name) -> Optional[ModuleType]: return None +class Components: + """Helper to load components.""" + + def __init__(self, hass): + """Initialize the Components class.""" + self._hass = hass + + def __getattr__(self, comp_name): + """Fetch a component.""" + component = get_component(comp_name) + if component is None: + raise ImportError('Unable to load {}'.format(comp_name)) + wrapped = ComponentWrapper(self._hass, component) + setattr(self, comp_name, wrapped) + return wrapped + + +class ComponentWrapper: + """Class to wrap a component and auto fill in hass argument.""" + + def __init__(self, hass, component): + """Initialize the component wrapper.""" + self._hass = hass + self._component = component + + def __getattr__(self, attr): + """Fetch an attribute.""" + value = getattr(self._component, attr) + + if hasattr(value, '__bind_hass'): + value = ft.partial(value, self._hass) + + setattr(self, attr, value) + return value + + +def bind_hass(func): + """Decorator to indicate that first argument is hass.""" + # pylint: disable=protected-access + func.__bind_hass = True + return func + + def load_order_component(comp_name: str) -> OrderedSet: """Return an OrderedSet of components in the correct order of loading. diff --git a/tests/test_loader.py b/tests/test_loader.py index 0b3f9653faa..6081b061ed2 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -1,11 +1,15 @@ """Test to verify that we can load components.""" # pylint: disable=protected-access +import asyncio import unittest +import pytest + import homeassistant.loader as loader import homeassistant.components.http as http -from tests.common import get_test_home_assistant, MockModule +from tests.common import ( + get_test_home_assistant, MockModule, async_mock_service) class TestLoader(unittest.TestCase): @@ -54,3 +58,29 @@ class TestLoader(unittest.TestCase): # Try to get load order for non-existing component self.assertEqual([], loader.load_order_component('mod1')) + + +def test_component_loader(hass): + """Test loading components.""" + components = loader.Components(hass) + assert components.http.CONFIG_SCHEMA is http.CONFIG_SCHEMA + assert hass.components.http.CONFIG_SCHEMA is http.CONFIG_SCHEMA + + +def test_component_loader_non_existing(hass): + """Test loading components.""" + components = loader.Components(hass) + with pytest.raises(ImportError): + components.non_existing + + +@asyncio.coroutine +def test_component_wrapper(hass): + """Test component wrapper.""" + calls = async_mock_service(hass, 'light', 'turn_on') + + components = loader.Components(hass) + components.light.async_turn_on('light.test') + yield from hass.async_block_till_done() + + assert len(calls) == 1 From d29bdddaa790908fbe611e65eab33a2bc61a4b9f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 16 Jul 2017 10:14:46 -0700 Subject: [PATCH 014/118] Add bind_hass to components (#8502) * Add bind_hass to components * Add bind_hass to group --- .../alarm_control_panel/__init__.py | 5 +++++ .../components/automation/__init__.py | 8 ++++++++ homeassistant/components/camera/__init__.py | 3 +++ homeassistant/components/climate/__init__.py | 9 +++++++++ homeassistant/components/cover/__init__.py | 10 ++++++++++ .../components/device_tracker/__init__.py | 2 ++ homeassistant/components/fan/__init__.py | 8 ++++++++ homeassistant/components/group.py | 11 ++++++++++ .../components/image_processing/__init__.py | 2 ++ homeassistant/components/input_boolean.py | 5 +++++ homeassistant/components/input_select.py | 5 +++++ homeassistant/components/input_slider.py | 2 ++ homeassistant/components/light/__init__.py | 5 +++++ homeassistant/components/lock/__init__.py | 4 ++++ .../components/media_player/__init__.py | 20 +++++++++++++++++++ homeassistant/components/mqtt/__init__.py | 6 ++++++ homeassistant/components/notify/__init__.py | 2 ++ .../components/persistent_notification.py | 5 +++++ homeassistant/components/python_script.py | 3 +++ homeassistant/components/remote/__init__.py | 5 +++++ homeassistant/components/scene/__init__.py | 2 ++ homeassistant/components/script.py | 6 ++++++ homeassistant/components/switch/__init__.py | 7 +++++++ homeassistant/components/zone.py | 3 +++ 24 files changed, 138 insertions(+) diff --git a/homeassistant/components/alarm_control_panel/__init__.py b/homeassistant/components/alarm_control_panel/__init__.py index 80c5e0ad1cc..39c86f3215f 100644 --- a/homeassistant/components/alarm_control_panel/__init__.py +++ b/homeassistant/components/alarm_control_panel/__init__.py @@ -15,6 +15,7 @@ from homeassistant.const import ( ATTR_CODE, ATTR_CODE_FORMAT, ATTR_ENTITY_ID, SERVICE_ALARM_TRIGGER, SERVICE_ALARM_DISARM, SERVICE_ALARM_ARM_HOME, SERVICE_ALARM_ARM_AWAY) from homeassistant.config import load_yaml_config_file +from homeassistant.loader import bind_hass from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity @@ -44,6 +45,7 @@ ALARM_SERVICE_SCHEMA = vol.Schema({ }) +@bind_hass def alarm_disarm(hass, code=None, entity_id=None): """Send the alarm the command for disarm.""" data = {} @@ -55,6 +57,7 @@ def alarm_disarm(hass, code=None, entity_id=None): hass.services.call(DOMAIN, SERVICE_ALARM_DISARM, data) +@bind_hass def alarm_arm_home(hass, code=None, entity_id=None): """Send the alarm the command for arm home.""" data = {} @@ -66,6 +69,7 @@ def alarm_arm_home(hass, code=None, entity_id=None): hass.services.call(DOMAIN, SERVICE_ALARM_ARM_HOME, data) +@bind_hass def alarm_arm_away(hass, code=None, entity_id=None): """Send the alarm the command for arm away.""" data = {} @@ -77,6 +81,7 @@ def alarm_arm_away(hass, code=None, entity_id=None): hass.services.call(DOMAIN, SERVICE_ALARM_ARM_AWAY, data) +@bind_hass def alarm_trigger(hass, code=None, entity_id=None): """Send the alarm the command for trigger.""" data = {} diff --git a/homeassistant/components/automation/__init__.py b/homeassistant/components/automation/__init__.py index 09f0e286755..27332bfaa9f 100644 --- a/homeassistant/components/automation/__init__.py +++ b/homeassistant/components/automation/__init__.py @@ -13,6 +13,7 @@ import voluptuous as vol from homeassistant.setup import async_prepare_setup_platform from homeassistant.core import CoreState +from homeassistant.loader import bind_hass from homeassistant import config as conf_util from homeassistant.const import ( ATTR_ENTITY_ID, CONF_PLATFORM, STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF, @@ -105,6 +106,7 @@ TRIGGER_SERVICE_SCHEMA = vol.Schema({ RELOAD_SERVICE_SCHEMA = vol.Schema({}) +@bind_hass def is_on(hass, entity_id): """ Return true if specified automation entity_id is on. @@ -114,35 +116,41 @@ def is_on(hass, entity_id): return hass.states.is_state(entity_id, STATE_ON) +@bind_hass def turn_on(hass, entity_id=None): """Turn on specified automation or all.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_TURN_ON, data) +@bind_hass def turn_off(hass, entity_id=None): """Turn off specified automation or all.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_TURN_OFF, data) +@bind_hass def toggle(hass, entity_id=None): """Toggle specified automation or all.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_TOGGLE, data) +@bind_hass def trigger(hass, entity_id=None): """Trigger specified automation or all.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_TRIGGER, data) +@bind_hass def reload(hass): """Reload the automation from config.""" hass.services.call(DOMAIN, SERVICE_RELOAD) +@bind_hass def async_reload(hass): """Reload the automation from config. diff --git a/homeassistant/components/camera/__init__.py b/homeassistant/components/camera/__init__.py index 5b97e102d8d..a7d778d99aa 100644 --- a/homeassistant/components/camera/__init__.py +++ b/homeassistant/components/camera/__init__.py @@ -23,6 +23,7 @@ from homeassistant.core import callback from homeassistant.const import (ATTR_ENTITY_ID, ATTR_ENTITY_PICTURE) from homeassistant.config import load_yaml_config_file from homeassistant.exceptions import HomeAssistantError +from homeassistant.loader import bind_hass from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent @@ -55,6 +56,7 @@ CAMERA_SERVICE_SCHEMA = vol.Schema({ }) +@bind_hass def enable_motion_detection(hass, entity_id=None): """Enable Motion Detection.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None @@ -62,6 +64,7 @@ def enable_motion_detection(hass, entity_id=None): DOMAIN, SERVICE_EN_MOTION, data)) +@bind_hass def disable_motion_detection(hass, entity_id=None): """Disable Motion Detection.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None diff --git a/homeassistant/components/climate/__init__.py b/homeassistant/components/climate/__init__.py index 5b6c025b3e3..6dd66817d43 100644 --- a/homeassistant/components/climate/__init__.py +++ b/homeassistant/components/climate/__init__.py @@ -14,6 +14,7 @@ from numbers import Number import voluptuous as vol from homeassistant.config import load_yaml_config_file +from homeassistant.loader import bind_hass from homeassistant.util.temperature import convert as convert_temperature from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity import Entity @@ -114,6 +115,7 @@ SET_SWING_MODE_SCHEMA = vol.Schema({ }) +@bind_hass def set_away_mode(hass, away_mode, entity_id=None): """Turn all or specified climate devices away mode on.""" data = { @@ -126,6 +128,7 @@ def set_away_mode(hass, away_mode, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_AWAY_MODE, data) +@bind_hass def set_hold_mode(hass, hold_mode, entity_id=None): """Set new hold mode.""" data = { @@ -138,6 +141,7 @@ def set_hold_mode(hass, hold_mode, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_HOLD_MODE, data) +@bind_hass def set_aux_heat(hass, aux_heat, entity_id=None): """Turn all or specified climate devices auxillary heater on.""" data = { @@ -150,6 +154,7 @@ def set_aux_heat(hass, aux_heat, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_AUX_HEAT, data) +@bind_hass def set_temperature(hass, temperature=None, entity_id=None, target_temp_high=None, target_temp_low=None, operation_mode=None): @@ -167,6 +172,7 @@ def set_temperature(hass, temperature=None, entity_id=None, hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, kwargs) +@bind_hass def set_humidity(hass, humidity, entity_id=None): """Set new target humidity.""" data = {ATTR_HUMIDITY: humidity} @@ -177,6 +183,7 @@ def set_humidity(hass, humidity, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_HUMIDITY, data) +@bind_hass def set_fan_mode(hass, fan, entity_id=None): """Set all or specified climate devices fan mode on.""" data = {ATTR_FAN_MODE: fan} @@ -187,6 +194,7 @@ def set_fan_mode(hass, fan, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_FAN_MODE, data) +@bind_hass def set_operation_mode(hass, operation_mode, entity_id=None): """Set new target operation mode.""" data = {ATTR_OPERATION_MODE: operation_mode} @@ -197,6 +205,7 @@ def set_operation_mode(hass, operation_mode, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_OPERATION_MODE, data) +@bind_hass def set_swing_mode(hass, swing_mode, entity_id=None): """Set new target swing mode.""" data = {ATTR_SWING_MODE: swing_mode} diff --git a/homeassistant/components/cover/__init__.py b/homeassistant/components/cover/__init__.py index d323ad324c7..df096c9ba80 100644 --- a/homeassistant/components/cover/__init__.py +++ b/homeassistant/components/cover/__init__.py @@ -13,6 +13,7 @@ import os import voluptuous as vol from homeassistant.config import load_yaml_config_file +from homeassistant.loader import bind_hass from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity import Entity from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa @@ -86,24 +87,28 @@ SERVICE_TO_METHOD = { } +@bind_hass def is_closed(hass, entity_id=None): """Return if the cover is closed based on the statemachine.""" entity_id = entity_id or ENTITY_ID_ALL_COVERS return hass.states.is_state(entity_id, STATE_CLOSED) +@bind_hass def open_cover(hass, entity_id=None): """Open all or specified cover.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None hass.services.call(DOMAIN, SERVICE_OPEN_COVER, data) +@bind_hass def close_cover(hass, entity_id=None): """Close all or specified cover.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None hass.services.call(DOMAIN, SERVICE_CLOSE_COVER, data) +@bind_hass def set_cover_position(hass, position, entity_id=None): """Move to specific position all or specified cover.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} @@ -111,24 +116,28 @@ def set_cover_position(hass, position, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_COVER_POSITION, data) +@bind_hass def stop_cover(hass, entity_id=None): """Stop all or specified cover.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None hass.services.call(DOMAIN, SERVICE_STOP_COVER, data) +@bind_hass def open_cover_tilt(hass, entity_id=None): """Open all or specified cover tilt.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None hass.services.call(DOMAIN, SERVICE_OPEN_COVER_TILT, data) +@bind_hass def close_cover_tilt(hass, entity_id=None): """Close all or specified cover tilt.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None hass.services.call(DOMAIN, SERVICE_CLOSE_COVER_TILT, data) +@bind_hass def set_cover_tilt_position(hass, tilt_position, entity_id=None): """Move to specific tilt position all or specified cover.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} @@ -136,6 +145,7 @@ def set_cover_tilt_position(hass, tilt_position, entity_id=None): hass.services.call(DOMAIN, SERVICE_SET_COVER_TILT_POSITION, data) +@bind_hass def stop_cover_tilt(hass, entity_id=None): """Stop all or specified cover tilt.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index 017bb723ee5..8192dfa751d 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -16,6 +16,7 @@ import voluptuous as vol from homeassistant.setup import async_prepare_setup_platform from homeassistant.core import callback +from homeassistant.loader import bind_hass from homeassistant.components import group, zone from homeassistant.components.discovery import SERVICE_NETGEAR from homeassistant.config import load_yaml_config_file, async_log_exception @@ -93,6 +94,7 @@ DISCOVERY_PLATFORMS = { } +@bind_hass def is_on(hass: HomeAssistantType, entity_id: str=None): """Return the state if any or a specified device is home.""" entity = entity_id or ENTITY_ID_ALL_DEVICES diff --git a/homeassistant/components/fan/__init__.py b/homeassistant/components/fan/__init__.py index 4642017ce32..fd12529cb48 100644 --- a/homeassistant/components/fan/__init__.py +++ b/homeassistant/components/fan/__init__.py @@ -17,6 +17,7 @@ from homeassistant.config import load_yaml_config_file from homeassistant.const import (SERVICE_TURN_ON, SERVICE_TOGGLE, SERVICE_TURN_OFF, ATTR_ENTITY_ID, STATE_UNKNOWN) +from homeassistant.loader import bind_hass from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa @@ -118,6 +119,7 @@ SERVICE_TO_METHOD = { } +@bind_hass def is_on(hass, entity_id: str=None) -> bool: """Return if the fans are on based on the statemachine.""" entity_id = entity_id or ENTITY_ID_ALL_FANS @@ -125,6 +127,7 @@ def is_on(hass, entity_id: str=None) -> bool: return state.attributes[ATTR_SPEED] not in [SPEED_OFF, STATE_UNKNOWN] +@bind_hass def turn_on(hass, entity_id: str=None, speed: str=None) -> None: """Turn all or specified fan on.""" data = { @@ -137,6 +140,7 @@ def turn_on(hass, entity_id: str=None, speed: str=None) -> None: hass.services.call(DOMAIN, SERVICE_TURN_ON, data) +@bind_hass def turn_off(hass, entity_id: str=None) -> None: """Turn all or specified fan off.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} @@ -144,6 +148,7 @@ def turn_off(hass, entity_id: str=None) -> None: hass.services.call(DOMAIN, SERVICE_TURN_OFF, data) +@bind_hass def toggle(hass, entity_id: str=None) -> None: """Toggle all or specified fans.""" data = { @@ -153,6 +158,7 @@ def toggle(hass, entity_id: str=None) -> None: hass.services.call(DOMAIN, SERVICE_TOGGLE, data) +@bind_hass def oscillate(hass, entity_id: str=None, should_oscillate: bool=True) -> None: """Set oscillation on all or specified fan.""" data = { @@ -165,6 +171,7 @@ def oscillate(hass, entity_id: str=None, should_oscillate: bool=True) -> None: hass.services.call(DOMAIN, SERVICE_OSCILLATE, data) +@bind_hass def set_speed(hass, entity_id: str=None, speed: str=None) -> None: """Set speed for all or specified fan.""" data = { @@ -177,6 +184,7 @@ def set_speed(hass, entity_id: str=None, speed: str=None) -> None: hass.services.call(DOMAIN, SERVICE_SET_SPEED, data) +@bind_hass def set_direction(hass, entity_id: str=None, direction: str=None) -> None: """Set direction for all or specified fan.""" data = { diff --git a/homeassistant/components/group.py b/homeassistant/components/group.py index d07e506e897..9985d129a3a 100644 --- a/homeassistant/components/group.py +++ b/homeassistant/components/group.py @@ -17,6 +17,7 @@ from homeassistant.const import ( STATE_UNLOCKED, STATE_OK, STATE_PROBLEM, STATE_UNKNOWN, ATTR_ASSUMED_STATE, SERVICE_RELOAD) from homeassistant.core import callback +from homeassistant.loader import bind_hass from homeassistant.helpers.entity import Entity, async_generate_entity_id from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.event import async_track_state_change @@ -108,6 +109,7 @@ def _get_group_on_off(state): return None, None +@bind_hass def is_on(hass, entity_id): """Test if the group state is in its ON-state.""" state = hass.states.get(entity_id) @@ -121,23 +123,27 @@ def is_on(hass, entity_id): return False +@bind_hass def reload(hass): """Reload the automation from config.""" hass.add_job(async_reload, hass) @callback +@bind_hass def async_reload(hass): """Reload the automation from config.""" hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_RELOAD)) +@bind_hass def set_visibility(hass, entity_id=None, visible=True): """Hide or shows a group.""" data = {ATTR_ENTITY_ID: entity_id, ATTR_VISIBLE: visible} hass.services.call(DOMAIN, SERVICE_SET_VISIBILITY, data) +@bind_hass def set_group(hass, object_id, name=None, entity_ids=None, visible=None, icon=None, view=None, control=None, add=None): """Create a new user group.""" @@ -147,6 +153,7 @@ def set_group(hass, object_id, name=None, entity_ids=None, visible=None, @callback +@bind_hass def async_set_group(hass, object_id, name=None, entity_ids=None, visible=None, icon=None, view=None, control=None, add=None): """Create a new user group.""" @@ -166,18 +173,21 @@ def async_set_group(hass, object_id, name=None, entity_ids=None, visible=None, hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_SET, data)) +@bind_hass def remove(hass, name): """Remove a user group.""" hass.add_job(async_remove, hass, name) @callback +@bind_hass def async_remove(hass, object_id): """Remove a user group.""" data = {ATTR_OBJECT_ID: object_id} hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_REMOVE, data)) +@bind_hass def expand_entity_ids(hass, entity_ids): """Return entity_ids with group entity ids replaced by their members. @@ -215,6 +225,7 @@ def expand_entity_ids(hass, entity_ids): return found_ids +@bind_hass def get_entity_ids(hass, entity_id, domain_filter=None): """Get members of this group. diff --git a/homeassistant/components/image_processing/__init__.py b/homeassistant/components/image_processing/__init__.py index fb1cddcad61..e6979087b6f 100644 --- a/homeassistant/components/image_processing/__init__.py +++ b/homeassistant/components/image_processing/__init__.py @@ -16,6 +16,7 @@ from homeassistant.config import load_yaml_config_file from homeassistant.const import ( ATTR_ENTITY_ID, CONF_NAME, CONF_ENTITY_ID) from homeassistant.exceptions import HomeAssistantError +from homeassistant.loader import bind_hass from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent from homeassistant.loader import get_component @@ -59,6 +60,7 @@ SERVICE_SCAN_SCHEMA = vol.Schema({ }) +@bind_hass def scan(hass, entity_id=None): """Force process a image.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None diff --git a/homeassistant/components/input_boolean.py b/homeassistant/components/input_boolean.py index e975e42bcdc..3c4efdce175 100644 --- a/homeassistant/components/input_boolean.py +++ b/homeassistant/components/input_boolean.py @@ -12,6 +12,7 @@ import voluptuous as vol from homeassistant.const import ( ATTR_ENTITY_ID, CONF_ICON, CONF_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_TOGGLE, STATE_ON) +from homeassistant.loader import bind_hass import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.entity_component import EntityComponent @@ -41,21 +42,25 @@ CONFIG_SCHEMA = vol.Schema({ }, extra=vol.ALLOW_EXTRA) +@bind_hass def is_on(hass, entity_id): """Test if input_boolean is True.""" return hass.states.is_state(entity_id, STATE_ON) +@bind_hass def turn_on(hass, entity_id): """Set input_boolean to True.""" hass.services.call(DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}) +@bind_hass def turn_off(hass, entity_id): """Set input_boolean to False.""" hass.services.call(DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}) +@bind_hass def toggle(hass, entity_id): """Set input_boolean to False.""" hass.services.call(DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: entity_id}) diff --git a/homeassistant/components/input_select.py b/homeassistant/components/input_select.py index c7f3a7f2236..f16b029c1d7 100644 --- a/homeassistant/components/input_select.py +++ b/homeassistant/components/input_select.py @@ -10,6 +10,7 @@ import logging import voluptuous as vol from homeassistant.const import ATTR_ENTITY_ID, CONF_ICON, CONF_NAME +from homeassistant.loader import bind_hass import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent @@ -77,6 +78,7 @@ CONFIG_SCHEMA = vol.Schema({ }, required=True, extra=vol.ALLOW_EXTRA) +@bind_hass def select_option(hass, entity_id, option): """Set value of input_select.""" hass.services.call(DOMAIN, SERVICE_SELECT_OPTION, { @@ -85,6 +87,7 @@ def select_option(hass, entity_id, option): }) +@bind_hass def select_next(hass, entity_id): """Set next value of input_select.""" hass.services.call(DOMAIN, SERVICE_SELECT_NEXT, { @@ -92,6 +95,7 @@ def select_next(hass, entity_id): }) +@bind_hass def select_previous(hass, entity_id): """Set previous value of input_select.""" hass.services.call(DOMAIN, SERVICE_SELECT_PREVIOUS, { @@ -99,6 +103,7 @@ def select_previous(hass, entity_id): }) +@bind_hass def set_options(hass, entity_id, options): """Set options of input_select.""" hass.services.call(DOMAIN, SERVICE_SET_OPTIONS, { diff --git a/homeassistant/components/input_slider.py b/homeassistant/components/input_slider.py index bd17376b2ef..5357878a0ce 100644 --- a/homeassistant/components/input_slider.py +++ b/homeassistant/components/input_slider.py @@ -12,6 +12,7 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_UNIT_OF_MEASUREMENT, CONF_ICON, CONF_NAME) +from homeassistant.loader import bind_hass from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.restore_state import async_get_last_state @@ -69,6 +70,7 @@ CONFIG_SCHEMA = vol.Schema({ }, required=True, extra=vol.ALLOW_EXTRA) +@bind_hass def select_value(hass, entity_id, value): """Set input_slider to value.""" hass.services.call(DOMAIN, SERVICE_SELECT_VALUE, { diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index 5f3caff511a..4e9fbbf81ab 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -148,12 +148,14 @@ def extract_info(state): return params +@bind_hass def is_on(hass, entity_id=None): """Return if the lights are on based on the statemachine.""" entity_id = entity_id or ENTITY_ID_ALL_LIGHTS return hass.states.is_state(entity_id, STATE_ON) +@bind_hass def turn_on(hass, entity_id=None, transition=None, brightness=None, brightness_pct=None, rgb_color=None, xy_color=None, color_temp=None, kelvin=None, white_value=None, @@ -193,12 +195,14 @@ def async_turn_on(hass, entity_id=None, transition=None, brightness=None, hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data)) +@bind_hass def turn_off(hass, entity_id=None, transition=None): """Turn all or specified light off.""" hass.add_job(async_turn_off, hass, entity_id, transition) @callback +@bind_hass def async_turn_off(hass, entity_id=None, transition=None): """Turn all or specified light off.""" data = { @@ -212,6 +216,7 @@ def async_turn_off(hass, entity_id=None, transition=None): DOMAIN, SERVICE_TURN_OFF, data)) +@bind_hass def toggle(hass, entity_id=None, transition=None): """Toggle all or specified light.""" data = { diff --git a/homeassistant/components/lock/__init__.py b/homeassistant/components/lock/__init__.py index 369f0c93b85..c64f77b3bd6 100644 --- a/homeassistant/components/lock/__init__.py +++ b/homeassistant/components/lock/__init__.py @@ -13,6 +13,7 @@ import os import voluptuous as vol from homeassistant.config import load_yaml_config_file +from homeassistant.loader import bind_hass from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity import Entity from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa @@ -43,12 +44,14 @@ LOCK_SERVICE_SCHEMA = vol.Schema({ _LOGGER = logging.getLogger(__name__) +@bind_hass def is_locked(hass, entity_id=None): """Return if the lock is locked based on the statemachine.""" entity_id = entity_id or ENTITY_ID_ALL_LOCKS return hass.states.is_state(entity_id, STATE_LOCKED) +@bind_hass def lock(hass, entity_id=None, code=None): """Lock all or specified locks.""" data = {} @@ -60,6 +63,7 @@ def lock(hass, entity_id=None, code=None): hass.services.call(DOMAIN, SERVICE_LOCK, data) +@bind_hass def unlock(hass, entity_id=None, code=None): """Unlock all or specified locks.""" data = {} diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index 35981d89d6d..a53f7f1367a 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -17,6 +17,7 @@ import async_timeout import voluptuous as vol from homeassistant.config import load_yaml_config_file +from homeassistant.loader import bind_hass from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa @@ -199,6 +200,7 @@ ATTR_TO_PROPERTY = [ ] +@bind_hass def is_on(hass, entity_id=None): """ Return true if specified media player entity_id is on. @@ -210,36 +212,42 @@ def is_on(hass, entity_id=None): for entity_id in entity_ids) +@bind_hass def turn_on(hass, entity_id=None): """Turn on specified media player or all.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_TURN_ON, data) +@bind_hass def turn_off(hass, entity_id=None): """Turn off specified media player or all.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_TURN_OFF, data) +@bind_hass def toggle(hass, entity_id=None): """Toggle specified media player or all.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_TOGGLE, data) +@bind_hass def volume_up(hass, entity_id=None): """Send the media player the command for volume up.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_VOLUME_UP, data) +@bind_hass def volume_down(hass, entity_id=None): """Send the media player the command for volume down.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_VOLUME_DOWN, data) +@bind_hass def mute_volume(hass, mute, entity_id=None): """Send the media player the command for muting the volume.""" data = {ATTR_MEDIA_VOLUME_MUTED: mute} @@ -250,6 +258,7 @@ def mute_volume(hass, mute, entity_id=None): hass.services.call(DOMAIN, SERVICE_VOLUME_MUTE, data) +@bind_hass def set_volume_level(hass, volume, entity_id=None): """Send the media player the command for setting the volume.""" data = {ATTR_MEDIA_VOLUME_LEVEL: volume} @@ -260,42 +269,49 @@ def set_volume_level(hass, volume, entity_id=None): hass.services.call(DOMAIN, SERVICE_VOLUME_SET, data) +@bind_hass def media_play_pause(hass, entity_id=None): """Send the media player the command for play/pause.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_MEDIA_PLAY_PAUSE, data) +@bind_hass def media_play(hass, entity_id=None): """Send the media player the command for play/pause.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_MEDIA_PLAY, data) +@bind_hass def media_pause(hass, entity_id=None): """Send the media player the command for pause.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_MEDIA_PAUSE, data) +@bind_hass def media_stop(hass, entity_id=None): """Send the media player the stop command.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_MEDIA_STOP, data) +@bind_hass def media_next_track(hass, entity_id=None): """Send the media player the command for next track.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_MEDIA_NEXT_TRACK, data) +@bind_hass def media_previous_track(hass, entity_id=None): """Send the media player the command for prev track.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_MEDIA_PREVIOUS_TRACK, data) +@bind_hass def media_seek(hass, position, entity_id=None): """Send the media player the command to seek in current playing media.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} @@ -303,6 +319,7 @@ def media_seek(hass, position, entity_id=None): hass.services.call(DOMAIN, SERVICE_MEDIA_SEEK, data) +@bind_hass def play_media(hass, media_type, media_id, entity_id=None, enqueue=None): """Send the media player the command for playing media.""" data = {ATTR_MEDIA_CONTENT_TYPE: media_type, @@ -317,6 +334,7 @@ def play_media(hass, media_type, media_id, entity_id=None, enqueue=None): hass.services.call(DOMAIN, SERVICE_PLAY_MEDIA, data) +@bind_hass def select_source(hass, source, entity_id=None): """Send the media player the command to select input source.""" data = {ATTR_INPUT_SOURCE: source} @@ -327,12 +345,14 @@ def select_source(hass, source, entity_id=None): hass.services.call(DOMAIN, SERVICE_SELECT_SOURCE, data) +@bind_hass def clear_playlist(hass, entity_id=None): """Send the media player the command for clear playlist.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else {} hass.services.call(DOMAIN, SERVICE_CLEAR_PLAYLIST, data) +@bind_hass def set_shuffle(hass, shuffle, entity_id=None): """Send the media player the command to enable/disable shuffle mode.""" data = {ATTR_MEDIA_SHUFFLE: shuffle} diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index f5a66412962..3c75648892b 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -19,6 +19,7 @@ from homeassistant.core import callback from homeassistant.setup import async_prepare_setup_platform from homeassistant.config import load_yaml_config_file from homeassistant.exceptions import HomeAssistantError +from homeassistant.loader import bind_hass from homeassistant.helpers import template, config_validation as cv from homeassistant.helpers.dispatcher import ( async_dispatcher_connect, dispatcher_send) @@ -180,12 +181,14 @@ def _build_publish_data(topic, qos, retain): return data +@bind_hass def publish(hass, topic, payload, qos=None, retain=None): """Publish message to an MQTT topic.""" hass.add_job(async_publish, hass, topic, payload, qos, retain) @callback +@bind_hass def async_publish(hass, topic, payload, qos=None, retain=None): """Publish message to an MQTT topic.""" data = _build_publish_data(topic, qos, retain) @@ -193,6 +196,7 @@ def async_publish(hass, topic, payload, qos=None, retain=None): hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_PUBLISH, data)) +@bind_hass def publish_template(hass, topic, payload_template, qos=None, retain=None): """Publish message to an MQTT topic using a template payload.""" data = _build_publish_data(topic, qos, retain) @@ -201,6 +205,7 @@ def publish_template(hass, topic, payload_template, qos=None, retain=None): @asyncio.coroutine +@bind_hass def async_subscribe(hass, topic, msg_callback, qos=DEFAULT_QOS, encoding='utf-8'): """Subscribe to an MQTT topic.""" @@ -232,6 +237,7 @@ def async_subscribe(hass, topic, msg_callback, qos=DEFAULT_QOS, return async_remove +@bind_hass def subscribe(hass, topic, msg_callback, qos=DEFAULT_QOS, encoding='utf-8'): """Subscribe to an MQTT topic.""" diff --git a/homeassistant/components/notify/__init__.py b/homeassistant/components/notify/__init__.py index f9f9d04c05c..1c17d1a795a 100644 --- a/homeassistant/components/notify/__init__.py +++ b/homeassistant/components/notify/__init__.py @@ -13,6 +13,7 @@ import voluptuous as vol from homeassistant.setup import async_prepare_setup_platform from homeassistant.exceptions import HomeAssistantError +from homeassistant.loader import bind_hass import homeassistant.helpers.config_validation as cv from homeassistant.config import load_yaml_config_file from homeassistant.const import CONF_NAME, CONF_PLATFORM @@ -51,6 +52,7 @@ NOTIFY_SERVICE_SCHEMA = vol.Schema({ }) +@bind_hass def send_message(hass, message, title=None, data=None): """Send a notification message.""" info = { diff --git a/homeassistant/components/persistent_notification.py b/homeassistant/components/persistent_notification.py index 212b2e7e7da..5e68aeee3ab 100644 --- a/homeassistant/components/persistent_notification.py +++ b/homeassistant/components/persistent_notification.py @@ -12,6 +12,7 @@ import voluptuous as vol from homeassistant.core import callback from homeassistant.exceptions import TemplateError +from homeassistant.loader import bind_hass from homeassistant.helpers import config_validation as cv from homeassistant.helpers.entity import async_generate_entity_id from homeassistant.util import slugify @@ -43,17 +44,20 @@ DEFAULT_OBJECT_ID = 'notification' _LOGGER = logging.getLogger(__name__) +@bind_hass def create(hass, message, title=None, notification_id=None): """Generate a notification.""" hass.add_job(async_create, hass, message, title, notification_id) +@bind_hass def dismiss(hass, notification_id): """Remove a notification.""" hass.add_job(async_dismiss, hass, notification_id) @callback +@bind_hass def async_create(hass, message, title=None, notification_id=None): """Generate a notification.""" data = { @@ -68,6 +72,7 @@ def async_create(hass, message, title=None, notification_id=None): @callback +@bind_hass def async_dismiss(hass, notification_id): """Remove a notification.""" data = {ATTR_NOTIFICATION_ID: notification_id} diff --git a/homeassistant/components/python_script.py b/homeassistant/components/python_script.py index c159bec0f75..66b9bd0112a 100644 --- a/homeassistant/components/python_script.py +++ b/homeassistant/components/python_script.py @@ -6,6 +6,7 @@ import logging import voluptuous as vol from homeassistant.exceptions import HomeAssistantError +from homeassistant.loader import bind_hass from homeassistant.util import sanitize_filename DOMAIN = 'python_script' @@ -49,6 +50,7 @@ def setup(hass, config): return True +@bind_hass def execute_script(hass, name, data=None): """Execute a script.""" filename = '{}.py'.format(name) @@ -57,6 +59,7 @@ def execute_script(hass, name, data=None): execute(hass, filename, source, data) +@bind_hass def execute(hass, filename, source, data=None): """Execute Python source.""" from RestrictedPython import compile_restricted_exec diff --git a/homeassistant/components/remote/__init__.py b/homeassistant/components/remote/__init__.py index 4e00a053cf9..bec4adcaa7e 100755 --- a/homeassistant/components/remote/__init__.py +++ b/homeassistant/components/remote/__init__.py @@ -13,6 +13,7 @@ import os import voluptuous as vol from homeassistant.config import load_yaml_config_file +from homeassistant.loader import bind_hass from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity import ToggleEntity import homeassistant.helpers.config_validation as cv @@ -62,12 +63,14 @@ REMOTE_SERVICE_SEND_COMMAND_SCHEMA = REMOTE_SERVICE_SCHEMA.extend({ }) +@bind_hass def is_on(hass, entity_id=None): """Return if the remote is on based on the statemachine.""" entity_id = entity_id or ENTITY_ID_ALL_REMOTES return hass.states.is_state(entity_id, STATE_ON) +@bind_hass def turn_on(hass, activity=None, entity_id=None): """Turn all or specified remote on.""" data = {ATTR_ACTIVITY: activity} @@ -76,12 +79,14 @@ def turn_on(hass, activity=None, entity_id=None): hass.services.call(DOMAIN, SERVICE_TURN_ON, data) +@bind_hass def turn_off(hass, entity_id=None): """Turn all or specified remote off.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None hass.services.call(DOMAIN, SERVICE_TURN_OFF, data) +@bind_hass def send_command(hass, device, command, entity_id=None, num_repeats=None, delay_secs=None): """Send a command to a device.""" diff --git a/homeassistant/components/scene/__init__.py b/homeassistant/components/scene/__init__.py index dd46f469a55..fbfe2b6959a 100644 --- a/homeassistant/components/scene/__init__.py +++ b/homeassistant/components/scene/__init__.py @@ -11,6 +11,7 @@ import voluptuous as vol from homeassistant.const import ( ATTR_ENTITY_ID, CONF_PLATFORM, SERVICE_TURN_ON) +from homeassistant.loader import bind_hass import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent @@ -56,6 +57,7 @@ SCENE_SERVICE_SCHEMA = vol.Schema({ }) +@bind_hass def activate(hass, entity_id=None): """Activate a scene.""" data = {} diff --git a/homeassistant/components/script.py b/homeassistant/components/script.py index 996cef10d77..62edb11b778 100644 --- a/homeassistant/components/script.py +++ b/homeassistant/components/script.py @@ -16,6 +16,7 @@ from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_TOGGLE, SERVICE_RELOAD, STATE_ON, CONF_ALIAS) from homeassistant.core import split_entity_id +from homeassistant.loader import bind_hass from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.entity_component import EntityComponent import homeassistant.helpers.config_validation as cv @@ -55,16 +56,19 @@ SCRIPT_TURN_ONOFF_SCHEMA = vol.Schema({ RELOAD_SERVICE_SCHEMA = vol.Schema({}) +@bind_hass def is_on(hass, entity_id): """Return if the script is on based on the statemachine.""" return hass.states.is_state(entity_id, STATE_ON) +@bind_hass def reload(hass): """Reload script component.""" hass.services.call(DOMAIN, SERVICE_RELOAD) +@bind_hass def turn_on(hass, entity_id, variables=None): """Turn script on.""" _, object_id = split_entity_id(entity_id) @@ -72,11 +76,13 @@ def turn_on(hass, entity_id, variables=None): hass.services.call(DOMAIN, object_id, variables) +@bind_hass def turn_off(hass, entity_id): """Turn script on.""" hass.services.call(DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}) +@bind_hass def toggle(hass, entity_id): """Toggle the script.""" hass.services.call(DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: entity_id}) diff --git a/homeassistant/components/switch/__init__.py b/homeassistant/components/switch/__init__.py index 2af79a54313..a53c6c5c01f 100644 --- a/homeassistant/components/switch/__init__.py +++ b/homeassistant/components/switch/__init__.py @@ -13,6 +13,7 @@ import voluptuous as vol from homeassistant.core import callback from homeassistant.config import load_yaml_config_file +from homeassistant.loader import bind_hass from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity import ToggleEntity from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa @@ -48,6 +49,7 @@ SWITCH_SERVICE_SCHEMA = vol.Schema({ _LOGGER = logging.getLogger(__name__) +@bind_hass def is_on(hass, entity_id=None): """Return if the switch is on based on the statemachine. @@ -57,24 +59,28 @@ def is_on(hass, entity_id=None): return hass.states.is_state(entity_id, STATE_ON) +@bind_hass def turn_on(hass, entity_id=None): """Turn all or specified switch on.""" hass.add_job(async_turn_on, hass, entity_id) @callback +@bind_hass def async_turn_on(hass, entity_id=None): """Turn all or specified switch on.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data)) +@bind_hass def turn_off(hass, entity_id=None): """Turn all or specified switch off.""" hass.add_job(async_turn_off, hass, entity_id) @callback +@bind_hass def async_turn_off(hass, entity_id=None): """Turn all or specified switch off.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None @@ -82,6 +88,7 @@ def async_turn_off(hass, entity_id=None): hass.services.async_call(DOMAIN, SERVICE_TURN_OFF, data)) +@bind_hass def toggle(hass, entity_id=None): """Toggle all or specified switch.""" data = {ATTR_ENTITY_ID: entity_id} if entity_id else None diff --git a/homeassistant/components/zone.py b/homeassistant/components/zone.py index e1a8b8e721b..712abfb1b6e 100644 --- a/homeassistant/components/zone.py +++ b/homeassistant/components/zone.py @@ -12,6 +12,7 @@ import voluptuous as vol from homeassistant.const import ( ATTR_HIDDEN, ATTR_LATITUDE, ATTR_LONGITUDE, CONF_NAME, CONF_LATITUDE, CONF_LONGITUDE, CONF_ICON) +from homeassistant.loader import bind_hass from homeassistant.helpers import config_per_platform from homeassistant.helpers.entity import Entity, async_generate_entity_id from homeassistant.util.async import run_callback_threadsafe @@ -50,6 +51,7 @@ PLATFORM_SCHEMA = vol.Schema({ }, extra=vol.ALLOW_EXTRA) +@bind_hass def active_zone(hass, latitude, longitude, radius=0): """Find the active zone for given latitude, longitude.""" return run_callback_threadsafe( @@ -57,6 +59,7 @@ def active_zone(hass, latitude, longitude, radius=0): ).result() +@bind_hass def async_active_zone(hass, latitude, longitude, radius=0): """Find the active zone for given latitude, longitude. From f6c3832e90ec83e63b4032750acad24549586401 Mon Sep 17 00:00:00 2001 From: Maikel Wever Date: Sun, 16 Jul 2017 19:27:48 +0200 Subject: [PATCH 015/118] Fix TP-Link device tracker regression since 0.49 (#8497) * Fix TP-Link device tracker regression since 0.49 This regression was introduced by #8322. Fix is to utf encode the password like the other TP-Link backends do. * Fix linting issue introduced in previous commit Commit in question: 677f3fbb7f821ee925364c8260d235dce4f0ddbe --- homeassistant/components/device_tracker/tplink.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/tplink.py b/homeassistant/components/device_tracker/tplink.py index 88b0abe8ce4..ccf0c2d01af 100755 --- a/homeassistant/components/device_tracker/tplink.py +++ b/homeassistant/components/device_tracker/tplink.py @@ -391,7 +391,8 @@ class Tplink5DeviceScanner(TplinkDeviceScanner): "Cache-Control": "no-cache" } - password_md5 = hashlib.md5(self.password).hexdigest().upper() + password_md5 = hashlib.md5( + self.password.encode('utf')).hexdigest().upper() # create a session to handle cookie easier session = requests.session() From d0275c80754ac4a73d453d4fce0ad6d755d46e3a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 16 Jul 2017 12:39:38 -0700 Subject: [PATCH 016/118] Persistent notification import (#8507) * Rewrite persistent notification creation * Update components.is_on to use auto loading * Fix two hass parameters --- homeassistant/components/__init__.py | 30 ++++++++--------- .../alarm_control_panel/simplisafe.py | 6 ++-- homeassistant/components/amcrest.py | 6 ++-- homeassistant/components/apple_tv.py | 14 +++----- homeassistant/components/arlo.py | 6 ++-- homeassistant/components/axis.py | 14 ++++---- homeassistant/components/configurator.py | 2 ++ homeassistant/components/cover/myq.py | 6 ++-- homeassistant/components/demo.py | 9 +++--- .../components/device_tracker/unifi.py | 6 ++-- homeassistant/components/google.py | 32 +++++++++---------- homeassistant/components/media_player/roku.py | 6 ++-- homeassistant/components/ring.py | 6 ++-- homeassistant/components/sensor/qnap.py | 9 +++--- homeassistant/components/switch/broadlink.py | 11 +++---- homeassistant/components/upnp.py | 8 ++--- 16 files changed, 70 insertions(+), 101 deletions(-) diff --git a/homeassistant/components/__init__.py b/homeassistant/components/__init__.py index ecbb8036464..1d437d35da7 100644 --- a/homeassistant/components/__init__.py +++ b/homeassistant/components/__init__.py @@ -15,7 +15,6 @@ import homeassistant.core as ha import homeassistant.config as conf_util from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.service import extract_entity_ids -from homeassistant.loader import get_component from homeassistant.const import ( ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE, SERVICE_HOMEASSISTANT_STOP, SERVICE_HOMEASSISTANT_RESTART, @@ -33,25 +32,27 @@ def is_on(hass, entity_id=None): If there is no entity id given we will check all. """ if entity_id: - group = get_component('group') - - entity_ids = group.expand_entity_ids(hass, [entity_id]) + entity_ids = hass.components.group.expand_entity_ids([entity_id]) else: entity_ids = hass.states.entity_ids() for ent_id in entity_ids: domain = ha.split_entity_id(ent_id)[0] - module = get_component(domain) - try: - if module.is_on(hass, ent_id): - return True + component = getattr(hass.components, domain) - except AttributeError: - # module is None or method is_on does not exist - _LOGGER.exception("Failed to call %s.is_on for %s", - module, ent_id) + except ImportError: + _LOGGER.error('Failed to call %s.is_on: component not found', + domain) + continue + + if not hasattr(component, 'is_on'): + _LOGGER.warning("Component %s has no is_on method.", domain) + continue + + if component.is_on(ent_id): + return True return False @@ -161,10 +162,9 @@ def async_setup(hass, config): return if errors: - notif = get_component('persistent_notification') _LOGGER.error(errors) - notif.async_create( - hass, "Config error. See dev-info panel for details.", + hass.components.persistent_notification.async_create( + "Config error. See dev-info panel for details.", "Config validating", "{0}.check_config".format(ha.DOMAIN)) return diff --git a/homeassistant/components/alarm_control_panel/simplisafe.py b/homeassistant/components/alarm_control_panel/simplisafe.py index fadfbc41a6f..913a3abb616 100644 --- a/homeassistant/components/alarm_control_panel/simplisafe.py +++ b/homeassistant/components/alarm_control_panel/simplisafe.py @@ -15,7 +15,6 @@ from homeassistant.const import ( STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY, EVENT_HOMEASSISTANT_STOP) import homeassistant.helpers.config_validation as cv -import homeassistant.loader as loader REQUIREMENTS = ['simplisafe-python==1.0.2'] @@ -42,7 +41,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) - persistent_notification = loader.get_component('persistent_notification') simplisafe = SimpliSafeApiInterface() status = simplisafe.set_credentials(username, password) if status: @@ -53,8 +51,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): else: message = 'Failed to log into SimpliSafe. Check credentials.' _LOGGER.error(message) - persistent_notification.create( - hass, message, + hass.components.persistent_notification.create( + message, title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID) return False diff --git a/homeassistant/components/amcrest.py b/homeassistant/components/amcrest.py index 8a40c790c12..9760ee5d607 100644 --- a/homeassistant/components/amcrest.py +++ b/homeassistant/components/amcrest.py @@ -11,7 +11,6 @@ import aiohttp import voluptuous as vol from requests.exceptions import HTTPError, ConnectTimeout -import homeassistant.loader as loader from homeassistant.const import ( CONF_NAME, CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD, CONF_SENSORS, CONF_SCAN_INTERVAL, HTTP_BASIC_AUTHENTICATION) @@ -92,7 +91,6 @@ def setup(hass, config): amcrest_cams = config[DOMAIN] - persistent_notification = loader.get_component('persistent_notification') for device in amcrest_cams: camera = AmcrestCamera(device.get(CONF_HOST), device.get(CONF_PORT), @@ -103,8 +101,8 @@ def setup(hass, config): except (ConnectTimeout, HTTPError) as ex: _LOGGER.error("Unable to connect to Amcrest camera: %s", str(ex)) - persistent_notification.create( - hass, 'Error: {}
' + hass.components.persistent_notification.create( + 'Error: {}
' 'You will need to restart hass after fixing.' ''.format(ex), title=NOTIFICATION_TITLE, diff --git a/homeassistant/components/apple_tv.py b/homeassistant/components/apple_tv.py index 17cc46f3318..948caa27538 100644 --- a/homeassistant/components/apple_tv.py +++ b/homeassistant/components/apple_tv.py @@ -15,7 +15,6 @@ from homeassistant.config import load_yaml_config_file from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers import discovery from homeassistant.components.discovery import SERVICE_APPLE_TV -from homeassistant.loader import get_component import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['pyatv==0.3.2'] @@ -66,27 +65,24 @@ APPLE_TV_AUTHENTICATE_SCHEMA = vol.Schema({ def request_configuration(hass, config, atv, credentials): """Request configuration steps from the user.""" - configurator = get_component('configurator') + configurator = hass.components.configurator @asyncio.coroutine def configuration_callback(callback_data): """Handle the submitted configuration.""" from pyatv import exceptions pin = callback_data.get('pin') - notification = get_component('persistent_notification') try: yield from atv.airplay.finish_authentication(pin) - notification.async_create( - hass, + hass.components.persistent_notification.async_create( 'Authentication succeeded!

Add the following ' 'to credentials: in your apple_tv configuration:

' '{0}'.format(credentials), title=NOTIFICATION_AUTH_TITLE, notification_id=NOTIFICATION_AUTH_ID) except exceptions.DeviceAuthenticationError as ex: - notification.async_create( - hass, + hass.components.persistent_notification.async_create( 'Authentication failed! Did you enter correct PIN?

' 'Details: {0}'.format(ex), title=NOTIFICATION_AUTH_TITLE, @@ -119,9 +115,7 @@ def scan_for_apple_tvs(hass): if not devices: devices = ['No device(s) found'] - notification = get_component('persistent_notification') - notification.async_create( - hass, + hass.components.persistent_notification.async_create( 'The following devices were found:

' + '

'.join(devices), title=NOTIFICATION_SCAN_TITLE, diff --git a/homeassistant/components/arlo.py b/homeassistant/components/arlo.py index 630420bd3e5..1ba2acb4fe0 100644 --- a/homeassistant/components/arlo.py +++ b/homeassistant/components/arlo.py @@ -9,7 +9,6 @@ import logging import voluptuous as vol from requests.exceptions import HTTPError, ConnectTimeout -import homeassistant.loader as loader from homeassistant.helpers import config_validation as cv from homeassistant.const import CONF_USERNAME, CONF_PASSWORD @@ -40,7 +39,6 @@ def setup(hass, config): username = conf.get(CONF_USERNAME) password = conf.get(CONF_PASSWORD) - persistent_notification = loader.get_component('persistent_notification') try: from pyarlo import PyArlo @@ -50,8 +48,8 @@ def setup(hass, config): hass.data[DATA_ARLO] = arlo except (ConnectTimeout, HTTPError) as ex: _LOGGER.error("Unable to connect to Netgar Arlo: %s", str(ex)) - persistent_notification.create( - hass, 'Error: {}
' + hass.components.persistent_notification.create( + 'Error: {}
' 'You will need to restart hass after fixing.' ''.format(ex), title=NOTIFICATION_TITLE, diff --git a/homeassistant/components/axis.py b/homeassistant/components/axis.py index bb1ec05496a..d83e07989e6 100644 --- a/homeassistant/components/axis.py +++ b/homeassistant/components/axis.py @@ -21,7 +21,6 @@ from homeassistant.helpers import config_validation as cv from homeassistant.helpers import discovery from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.entity import Entity -from homeassistant.loader import get_component REQUIREMENTS = ['axis==8'] @@ -79,7 +78,7 @@ SERVICE_SCHEMA = vol.Schema({ def request_configuration(hass, name, host, serialnumber): """Request configuration steps from the user.""" - configurator = get_component('configurator') + configurator = hass.components.configurator def configuration_callback(callback_data): """Called when config is submitted.""" @@ -242,12 +241,11 @@ def setup_device(hass, config): if enable_metadatastream: device.initialize_new_event = event_initialized if not device.initiate_metadatastream(): - notification = get_component('persistent_notification') - notification.create(hass, - 'Dependency missing for sensors, ' - 'please check documentation', - title=DOMAIN, - notification_id='axis_notification') + hass.components.persistent_notification.create( + 'Dependency missing for sensors, ' + 'please check documentation', + title=DOMAIN, + notification_id='axis_notification') AXIS_DEVICES[device.serial_number] = device diff --git a/homeassistant/components/configurator.py b/homeassistant/components/configurator.py index e502e0a0253..660a62a5b89 100644 --- a/homeassistant/components/configurator.py +++ b/homeassistant/components/configurator.py @@ -12,6 +12,7 @@ import logging from homeassistant.core import callback as async_callback from homeassistant.const import EVENT_TIME_CHANGED, ATTR_FRIENDLY_NAME, \ ATTR_ENTITY_PICTURE +from homeassistant.loader import bind_hass from homeassistant.helpers.entity import generate_entity_id from homeassistant.util.async import run_callback_threadsafe @@ -37,6 +38,7 @@ STATE_CONFIGURE = 'configure' STATE_CONFIGURED = 'configured' +@bind_hass def request_config( hass, name, callback, description=None, description_image=None, submit_caption=None, fields=None, link_name=None, link_url=None, diff --git a/homeassistant/components/cover/myq.py b/homeassistant/components/cover/myq.py index 4c862f8c8b8..8d59a90278c 100644 --- a/homeassistant/components/cover/myq.py +++ b/homeassistant/components/cover/myq.py @@ -12,7 +12,6 @@ from homeassistant.components.cover import CoverDevice from homeassistant.const import ( CONF_USERNAME, CONF_PASSWORD, CONF_TYPE, STATE_CLOSED) import homeassistant.helpers.config_validation as cv -import homeassistant.loader as loader REQUIREMENTS = ['pymyq==0.0.8'] @@ -37,7 +36,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) brand = config.get(CONF_TYPE) - persistent_notification = loader.get_component('persistent_notification') myq = pymyq(username, password, brand) try: @@ -52,8 +50,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): except (TypeError, KeyError, NameError, ValueError) as ex: _LOGGER.error("%s", ex) - persistent_notification.create( - hass, 'Error: {}
' + hass.components.persistent_notification.create( + 'Error: {}
' 'You will need to restart hass after fixing.' ''.format(ex), title=NOTIFICATION_TITLE, diff --git a/homeassistant/components/demo.py b/homeassistant/components/demo.py index 222a031d380..27bb1bbb8d1 100644 --- a/homeassistant/components/demo.py +++ b/homeassistant/components/demo.py @@ -9,7 +9,6 @@ import time import homeassistant.bootstrap as bootstrap import homeassistant.core as ha -import homeassistant.loader as loader from homeassistant.const import ATTR_ENTITY_ID, CONF_PLATFORM DEPENDENCIES = ['conversation', 'introduction', 'zone'] @@ -38,9 +37,9 @@ COMPONENTS_WITH_DEMO_PLATFORM = [ @asyncio.coroutine def async_setup(hass, config): """Set up the demo environment.""" - group = loader.get_component('group') - configurator = loader.get_component('configurator') - persistent_notification = loader.get_component('persistent_notification') + group = hass.components.group + configurator = hass.components.configurator + persistent_notification = hass.components.persistent_notification config.setdefault(ha.DOMAIN, {}) config.setdefault(DOMAIN, {}) @@ -206,7 +205,7 @@ def async_setup(hass, config): def setup_configurator(): """Set up a configurator.""" request_id = configurator.request_config( - hass, "Philips Hue", hue_configuration_callback, + "Philips Hue", hue_configuration_callback, description=("Press the button on the bridge to register Philips " "Hue with Home Assistant."), description_image="/static/images/config_philips_hue.jpg", diff --git a/homeassistant/components/device_tracker/unifi.py b/homeassistant/components/device_tracker/unifi.py index 29c997b4dac..a471ca5c96a 100644 --- a/homeassistant/components/device_tracker/unifi.py +++ b/homeassistant/components/device_tracker/unifi.py @@ -8,7 +8,6 @@ import logging 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, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD @@ -48,14 +47,13 @@ def get_scanner(hass, config): port = config[DOMAIN].get(CONF_PORT) verify_ssl = config[DOMAIN].get(CONF_VERIFY_SSL) - persistent_notification = loader.get_component('persistent_notification') try: ctrl = Controller(host, username, password, port, version='v4', site_id=site_id, ssl_verify=verify_ssl) except APIError as ex: _LOGGER.error("Failed to connect to Unifi: %s", ex) - persistent_notification.create( - hass, 'Failed to connect to Unifi. ' + hass.components.persistent_notification.create( + 'Failed to connect to Unifi. ' 'Error: {}
' 'You will need to restart hass after fixing.' ''.format(ex), diff --git a/homeassistant/components/google.py b/homeassistant/components/google.py index f7f8e63167f..e99c4095f22 100644 --- a/homeassistant/components/google.py +++ b/homeassistant/components/google.py @@ -17,7 +17,6 @@ import voluptuous as vol from voluptuous.error import Error as VoluptuousError import homeassistant.helpers.config_validation as cv -import homeassistant.loader as loader from homeassistant.setup import setup_component from homeassistant.helpers import discovery from homeassistant.helpers.entity import generate_entity_id @@ -106,32 +105,31 @@ def do_authentication(hass, config): 'Home-Assistant.io', ) - persistent_notification = loader.get_component('persistent_notification') try: dev_flow = oauth.step1_get_device_and_user_codes() except OAuth2DeviceCodeError as err: - persistent_notification.create( - hass, 'Error: {}
You will need to restart hass after fixing.' - ''.format(err), + hass.components.persistent_notification.create( + 'Error: {}
You will need to restart hass after fixing.' + ''.format(err), title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID) return False - persistent_notification.create( - hass, 'In order to authorize Home-Assistant to view your calendars ' - 'you must visit: {} and enter ' - 'code: {}'.format(dev_flow.verification_url, - dev_flow.verification_url, - dev_flow.user_code), + hass.components.persistent_notification.create( + 'In order to authorize Home-Assistant to view your calendars ' + 'you must visit: {} and enter ' + 'code: {}'.format(dev_flow.verification_url, + dev_flow.verification_url, + dev_flow.user_code), title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID ) def step2_exchange(now): """Keep trying to validate the user_code until it expires.""" if now >= dt.as_local(dev_flow.user_code_expiry): - persistent_notification.create( - hass, 'Authenication code expired, please restart ' - 'Home-Assistant and try again', + hass.components.persistent_notification.create( + 'Authenication code expired, please restart ' + 'Home-Assistant and try again', title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID) listener() @@ -146,9 +144,9 @@ def do_authentication(hass, config): storage.put(credentials) do_setup(hass, config) listener() - persistent_notification.create( - hass, 'We are all setup now. Check {} for calendars that have ' - 'been found'.format(YAML_DEVICES), + hass.components.persistent_notification.create( + 'We are all setup now. Check {} for calendars that have ' + 'been found'.format(YAML_DEVICES), title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID) listener = track_time_change(hass, step2_exchange, diff --git a/homeassistant/components/media_player/roku.py b/homeassistant/components/media_player/roku.py index aac6b1a228d..5917f1e3083 100644 --- a/homeassistant/components/media_player/roku.py +++ b/homeassistant/components/media_player/roku.py @@ -15,7 +15,6 @@ from homeassistant.components.media_player import ( from homeassistant.const import ( CONF_HOST, STATE_IDLE, STATE_PLAYING, STATE_UNKNOWN, STATE_HOME) import homeassistant.helpers.config_validation as cv -import homeassistant.loader as loader REQUIREMENTS = ['python-roku==3.1.3'] @@ -52,7 +51,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): elif CONF_HOST in config: hosts.append(config.get(CONF_HOST)) - persistent_notification = loader.get_component('persistent_notification') rokus = [] for host in hosts: new_roku = RokuDevice(host) @@ -66,8 +64,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): except AttributeError: _LOGGER.error("Unable to initialize roku at %s", host) - persistent_notification.create( - hass, 'Error: Unable to initialize roku at {}
' + hass.components.persistent_notification.create( + 'Error: Unable to initialize roku at {}
' 'Check its network connection or consider ' 'using auto discovery.
' 'You will need to restart hass after fixing.' diff --git a/homeassistant/components/ring.py b/homeassistant/components/ring.py index 450ef6b1978..a1529fddbd6 100644 --- a/homeassistant/components/ring.py +++ b/homeassistant/components/ring.py @@ -9,7 +9,6 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.const import CONF_USERNAME, CONF_PASSWORD -import homeassistant.loader as loader from requests.exceptions import HTTPError, ConnectTimeout @@ -40,7 +39,6 @@ def setup(hass, config): username = conf.get(CONF_USERNAME) password = conf.get(CONF_PASSWORD) - persistent_notification = loader.get_component('persistent_notification') try: from ring_doorbell import Ring @@ -51,8 +49,8 @@ def setup(hass, config): hass.data['ring'] = ring except (ConnectTimeout, HTTPError) as ex: _LOGGER.error("Unable to connect to Ring service: %s", str(ex)) - persistent_notification.create( - hass, 'Error: {}
' + hass.components.persistent_notification.create( + 'Error: {}
' 'You will need to restart hass after fixing.' ''.format(ex), title=NOTIFICATION_TITLE, diff --git a/homeassistant/components/sensor/qnap.py b/homeassistant/components/sensor/qnap.py index 42f68a1967a..20460f9063c 100644 --- a/homeassistant/components/sensor/qnap.py +++ b/homeassistant/components/sensor/qnap.py @@ -110,11 +110,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): api.update() if not api.data: - import homeassistant.loader as loader - loader.get_component('persistent_notification').create( - hass, 'Error: Failed to set up QNAP sensor.
' - 'Check the logs for additional information. ' - 'You will need to restart hass after fixing.', + hass.components.persistent_notification.create( + 'Error: Failed to set up QNAP sensor.
' + 'Check the logs for additional information. ' + 'You will need to restart hass after fixing.', title=NOTIFICATION_TITLE, notification_id=NOTIFICATION_ID) return False diff --git a/homeassistant/components/switch/broadlink.py b/homeassistant/components/switch/broadlink.py index 3a7f3ee0c80..6ea738d82bc 100644 --- a/homeassistant/components/switch/broadlink.py +++ b/homeassistant/components/switch/broadlink.py @@ -13,7 +13,6 @@ 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 ( @@ -67,8 +66,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): config.get(CONF_MAC).encode().replace(b':', b'')) switch_type = config.get(CONF_TYPE) - persistent_notification = loader.get_component('persistent_notification') - @asyncio.coroutine def _learn_command(call): try: @@ -91,13 +88,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None): log_msg = "Recieved packet is: {}".\ format(b64encode(packet).decode('utf8')) _LOGGER.info(log_msg) - persistent_notification.async_create( - hass, log_msg, title='Broadlink switch') + hass.components.persistent_notification.async_create( + 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.components.persistent_notification.async_create( + "Did not received any signal", title='Broadlink switch') @asyncio.coroutine def _send_packet(call): diff --git a/homeassistant/components/upnp.py b/homeassistant/components/upnp.py index 355a6d0a648..9e45def63db 100644 --- a/homeassistant/components/upnp.py +++ b/homeassistant/components/upnp.py @@ -9,8 +9,6 @@ from urllib.parse import urlsplit import voluptuous as vol -import homeassistant.loader as loader - from homeassistant.const import (EVENT_HOMEASSISTANT_STOP) from homeassistant.helpers import config_validation as cv from homeassistant.helpers import discovery @@ -78,8 +76,6 @@ def setup(hass, config): if external_port == 0: external_port = internal_port - persistent_notification = loader.get_component('persistent_notification') - try: upnp.addportmapping( external_port, 'TCP', host, internal_port, 'Home Assistant', '') @@ -92,8 +88,8 @@ def setup(hass, config): except Exception as ex: _LOGGER.error("UPnP failed to configure port mapping: %s", str(ex)) - persistent_notification.create( - hass, 'ERROR: tcp port {} is already mapped in your router.' + hass.components.persistent_notification.create( + 'ERROR: tcp port {} is already mapped in your router.' '
Please disable port_mapping in the upnp ' 'configuration section.
' 'You will need to restart hass after fixing.' From ffd3081743e5e0d0ba2051aa0d93e6a648fdd3ca Mon Sep 17 00:00:00 2001 From: Alexander Rust Date: Sun, 16 Jul 2017 21:43:47 +0200 Subject: [PATCH 017/118] Added additional attributes to OwnTracks device_tracker (#8503) * Added additional attributes to OwnTracks device_tracker * Added missing space after : --- homeassistant/components/device_tracker/owntracks.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/owntracks.py b/homeassistant/components/device_tracker/owntracks.py index f88fda03cf7..ab4ba315c02 100644 --- a/homeassistant/components/device_tracker/owntracks.py +++ b/homeassistant/components/device_tracker/owntracks.py @@ -353,12 +353,20 @@ def _parse_see_args(topic, data): kwargs = { 'dev_id': dev_id, 'host_name': host_name, - 'gps': (data[WAYPOINT_LAT_KEY], data[WAYPOINT_LON_KEY]) + 'gps': (data[WAYPOINT_LAT_KEY], data[WAYPOINT_LON_KEY]), + 'attributes': {} } if 'acc' in data: kwargs['gps_accuracy'] = data['acc'] if 'batt' in data: kwargs['battery'] = data['batt'] + if 'vel' in data: + kwargs['attributes']['velocity'] = data['vel'] + if 'tid' in data: + kwargs['attributes']['tid'] = data['tid'] + if 'addr' in data: + kwargs['attributes']['address'] = data['addr'] + return dev_id, kwargs From 8c9557401fc11790ab5ddf08c1e09e3ba3d56743 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 17 Jul 2017 11:03:16 +0200 Subject: [PATCH 018/118] Update dlib_face_detect.py (#8516) --- homeassistant/components/image_processing/dlib_face_detect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/image_processing/dlib_face_detect.py b/homeassistant/components/image_processing/dlib_face_detect.py index 7c0c0e26649..b4ad10934f2 100644 --- a/homeassistant/components/image_processing/dlib_face_detect.py +++ b/homeassistant/components/image_processing/dlib_face_detect.py @@ -68,4 +68,4 @@ class DlibFaceDetectEntity(ImageProcessingFaceEntity): image = face_recognition.load_image_file(fak_file) face_locations = face_recognition.face_locations(image) - self.process_faces(face_locations, len(face_locations)) + self.process_faces(list(face_locations), len(face_locations)) From 40aafcdf5df2abb10dd9ae08ecc6b9349f6d0244 Mon Sep 17 00:00:00 2001 From: Russell Cloran Date: Mon, 17 Jul 2017 02:25:20 -0700 Subject: [PATCH 019/118] prometheus: Convert fahrenheit to celsius (#8511) --- homeassistant/components/prometheus.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/homeassistant/components/prometheus.py b/homeassistant/components/prometheus.py index 4ed6028ac56..18a3a932d36 100644 --- a/homeassistant/components/prometheus.py +++ b/homeassistant/components/prometheus.py @@ -17,6 +17,7 @@ from homeassistant.const import (CONF_DOMAINS, CONF_ENTITIES, CONF_EXCLUDE, TEMP_CELSIUS, TEMP_FAHRENHEIT) from homeassistant import core as hacore from homeassistant.helpers import state as state_helper +from homeassistant.util.temperature import fahrenheit_to_celsius _LOGGER = logging.getLogger(__name__) @@ -198,6 +199,8 @@ class Metrics: metric = self._metric(*metric) try: value = state_helper.state_as_number(state) + if unit == TEMP_FAHRENHEIT: + value = fahrenheit_to_celsius(value) metric.labels(**self._labels(state)).set(value) except ValueError: pass From f0479855bdfff3140ccf761fcb8c9ac247691157 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 17 Jul 2017 12:09:42 +0200 Subject: [PATCH 020/118] Realfix for dlib (#8517) * Update dlib_face_detect.py * fix lint * Update dlib_face_detect.py --- .../components/image_processing/dlib_face_detect.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/image_processing/dlib_face_detect.py b/homeassistant/components/image_processing/dlib_face_detect.py index b4ad10934f2..1c999782ec7 100644 --- a/homeassistant/components/image_processing/dlib_face_detect.py +++ b/homeassistant/components/image_processing/dlib_face_detect.py @@ -19,6 +19,8 @@ REQUIREMENTS = ['face_recognition==0.2.0'] _LOGGER = logging.getLogger(__name__) +ATTR_LOCATION = 'location' + def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Dlib Face detection platform.""" @@ -68,4 +70,7 @@ class DlibFaceDetectEntity(ImageProcessingFaceEntity): image = face_recognition.load_image_file(fak_file) face_locations = face_recognition.face_locations(image) - self.process_faces(list(face_locations), len(face_locations)) + face_locations = [{ATTR_LOCATION: location} + for location in face_locations] + + self.process_faces(face_locations, len(face_locations)) From cca0d3ed446e0e9842390cdb18207d121a0a4210 Mon Sep 17 00:00:00 2001 From: Eugenio Panadero Date: Mon, 17 Jul 2017 13:47:28 +0200 Subject: [PATCH 021/118] Attach the `chat_id` for a callback query from a chat group (fixes #8461) (#8523) --- homeassistant/components/telegram_bot/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/components/telegram_bot/__init__.py b/homeassistant/components/telegram_bot/__init__.py index 3d16252120b..6d9f43e2425 100644 --- a/homeassistant/components/telegram_bot/__init__.py +++ b/homeassistant/components/telegram_bot/__init__.py @@ -581,6 +581,8 @@ class BaseTelegramBotEntity: data[ATTR_FROM_LAST] = msg_data['from']['last_name'] if 'chat' in msg_data: data[ATTR_CHAT_ID] = msg_data['chat']['id'] + elif ATTR_MESSAGE in msg_data and 'chat' in msg_data[ATTR_MESSAGE]: + data[ATTR_CHAT_ID] = msg_data[ATTR_MESSAGE]['chat']['id'] return True, data From 1a1571cd520f7bd8192b443625d8887d7e1f3ce6 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Mon, 17 Jul 2017 13:21:41 -0400 Subject: [PATCH 022/118] Added sensor state rounding (#8499) --- homeassistant/components/sensor/pi_hole.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/pi_hole.py b/homeassistant/components/sensor/pi_hole.py index bacb25ce2c4..f788fc8fd17 100644 --- a/homeassistant/components/sensor/pi_hole.py +++ b/homeassistant/components/sensor/pi_hole.py @@ -104,7 +104,10 @@ class PiHoleSensor(Entity): @property def state(self): """Return the state of the device.""" - return self._api.data[self._var_id] + try: + return round(self._api.data[self._var_id], 2) + except TypeError: + return self._api.data[self._var_id] # pylint: disable=no-member @property From c67c20f75205ad6da5c120a3736847a2eb9e9c1e Mon Sep 17 00:00:00 2001 From: Mike Christianson Date: Mon, 17 Jul 2017 10:45:42 -0700 Subject: [PATCH 023/118] fix for a bug introduced with media support in #8282 (#8513) data may be None if twitter data property unconfigured: File "/opt/homeassistant/homeassistant_venv/lib/python3.4/site-packages/homeassistant/components/notify/twitter.py", line 63, in send_message media = data.get(ATTR_MEDIA) --- homeassistant/components/notify/twitter.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/notify/twitter.py b/homeassistant/components/notify/twitter.py index 6d74f86132a..43efd2c2732 100644 --- a/homeassistant/components/notify/twitter.py +++ b/homeassistant/components/notify/twitter.py @@ -60,10 +60,13 @@ class TwitterNotificationService(BaseNotificationService): def send_message(self, message="", **kwargs): """Tweet a message, optionally with media.""" data = kwargs.get(ATTR_DATA) - media = data.get(ATTR_MEDIA) - if not self.hass.config.is_allowed_path(media): - _LOGGER.warning("'%s' is not in a whitelisted area.", media) - return + + media = None + if data: + media = data.get(ATTR_MEDIA) + if not self.hass.config.is_allowed_path(media): + _LOGGER.warning("'%s' is not in a whitelisted area.", media) + return media_id = self.upload_media(media) From 95e00279240e282c9a060d230ef2aaea33646a6d Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 17 Jul 2017 20:21:16 +0200 Subject: [PATCH 024/118] Fix KeyError --- homeassistant/components/notify/twitter.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/notify/twitter.py b/homeassistant/components/notify/twitter.py index 43efd2c2732..74002b89c76 100644 --- a/homeassistant/components/notify/twitter.py +++ b/homeassistant/components/notify/twitter.py @@ -65,7 +65,7 @@ class TwitterNotificationService(BaseNotificationService): if data: media = data.get(ATTR_MEDIA) if not self.hass.config.is_allowed_path(media): - _LOGGER.warning("'%s' is not in a whitelisted area.", media) + _LOGGER.warning("'%s' is not a whitelisted directory", media) return media_id = self.upload_media(media) @@ -97,8 +97,7 @@ class TwitterNotificationService(BaseNotificationService): return None media_id = resp.json()['media_id'] - media_id = self.upload_media_chunked(file, total_bytes, - media_id) + media_id = self.upload_media_chunked(file, total_bytes, media_id) resp = self.upload_media_finalize(media_id) if 199 > resp.status_code < 300: @@ -150,8 +149,8 @@ class TwitterNotificationService(BaseNotificationService): def log_error_resp(resp): """Log error response.""" obj = json.loads(resp.text) - error_message = obj['error'] - _LOGGER.error("Error %s : %s", resp.status_code, error_message) + error_message = obj['errors'] + _LOGGER.error("Error %s: %s", resp.status_code, error_message) @staticmethod def log_error_resp_append(resp): @@ -159,5 +158,5 @@ class TwitterNotificationService(BaseNotificationService): obj = json.loads(resp.text) error_message = obj['errors'][0]['message'] error_code = obj['errors'][0]['code'] - _LOGGER.error("Error %s : %s (Code %s)", resp.status_code, + _LOGGER.error("Error %s: %s (Code %s)", resp.status_code, error_message, error_code) From 8c9b3898fcda136a7ead6c81143894bc6007fc20 Mon Sep 17 00:00:00 2001 From: Eugenio Panadero Date: Mon, 17 Jul 2017 22:16:18 +0200 Subject: [PATCH 025/118] handle timeout errors without logging.exception when updating hue lights; double quotes in log msgs (#8524) --- homeassistant/components/light/hue.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/light/hue.py b/homeassistant/components/light/hue.py index 3344de02e75..cdbea7d2194 100644 --- a/homeassistant/components/light/hue.py +++ b/homeassistant/components/light/hue.py @@ -115,7 +115,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): if discovery_info is not None: if "HASS Bridge" in discovery_info.get('name', ''): - _LOGGER.info('Emulated hue found, will not add') + _LOGGER.info("Emulated hue found, will not add") return False host = discovery_info.get('host') @@ -126,7 +126,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): host = _find_host_from_config(hass, filename) if host is None: - _LOGGER.error('No host found in configuration') + _LOGGER.error("No host found in configuration") return False # Only act if we are not already configuring this host @@ -180,6 +180,12 @@ def setup_bridge(host, hass, add_devices, filename, allow_unreachable, try: api = bridge.get_api() + except phue.PhueRequestTimeout: + _LOGGER.warning("Timeout trying to reach the bridge") + return + except ConnectionRefusedError: + _LOGGER.error("The bridge refused the connection") + return except socket.error: # socket.error when we cannot reach Hue _LOGGER.exception("Cannot reach the bridge") @@ -221,8 +227,8 @@ def setup_bridge(host, hass, add_devices, filename, allow_unreachable, 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.') + _LOGGER.warning("Group info does not contain state. " + "Please update your hub.") skip_groups = True break From b83ff739bc20e1e43486a0d4186446a19896272a Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Mon, 17 Jul 2017 22:24:05 +0200 Subject: [PATCH 026/118] Remove deprecated automation keywords (#8510) * Remove deprecated automation keywords * Remove retired test case * Remove retired keyword --- homeassistant/components/automation/state.py | 8 ++------ homeassistant/components/automation/time.py | 11 ++--------- tests/components/automation/test_state.py | 19 ------------------- 3 files changed, 4 insertions(+), 34 deletions(-) diff --git a/homeassistant/components/automation/state.py b/homeassistant/components/automation/state.py index fbd1570a1e0..8ad5c40bb80 100644 --- a/homeassistant/components/automation/state.py +++ b/homeassistant/components/automation/state.py @@ -12,13 +12,11 @@ import homeassistant.util.dt as dt_util from homeassistant.const import MATCH_ALL, CONF_PLATFORM from homeassistant.helpers.event import ( async_track_state_change, async_track_point_in_utc_time) -from homeassistant.helpers.deprecation import get_deprecated import homeassistant.helpers.config_validation as cv CONF_ENTITY_ID = 'entity_id' CONF_FROM = 'from' CONF_TO = 'to' -CONF_STATE = 'state' CONF_FOR = 'for' TRIGGER_SCHEMA = vol.All( @@ -28,11 +26,9 @@ TRIGGER_SCHEMA = vol.All( # These are str on purpose. Want to catch YAML conversions CONF_FROM: str, CONF_TO: str, - CONF_STATE: str, CONF_FOR: vol.All(cv.time_period, cv.positive_timedelta), }), - vol.Any(cv.key_dependency(CONF_FOR, CONF_TO), - cv.key_dependency(CONF_FOR, CONF_STATE)) + cv.key_dependency(CONF_FOR, CONF_TO), ) @@ -41,7 +37,7 @@ def async_trigger(hass, config, action): """Listen for state changes based on configuration.""" entity_id = config.get(CONF_ENTITY_ID) from_state = config.get(CONF_FROM, MATCH_ALL) - to_state = get_deprecated(config, CONF_TO, CONF_STATE, MATCH_ALL) + to_state = config.get(CONF_TO, MATCH_ALL) time_delta = config.get(CONF_FOR) async_remove_state_for_cancel = None async_remove_state_for_listener = None diff --git a/homeassistant/components/automation/time.py b/homeassistant/components/automation/time.py index 8ba082e3331..a3a8496c3c5 100644 --- a/homeassistant/components/automation/time.py +++ b/homeassistant/components/automation/time.py @@ -10,7 +10,7 @@ import logging import voluptuous as vol from homeassistant.core import callback -from homeassistant.const import CONF_AT, CONF_PLATFORM, CONF_AFTER +from homeassistant.const import CONF_AT, CONF_PLATFORM from homeassistant.helpers import config_validation as cv from homeassistant.helpers.event import async_track_time_change @@ -23,12 +23,10 @@ _LOGGER = logging.getLogger(__name__) TRIGGER_SCHEMA = vol.All(vol.Schema({ vol.Required(CONF_PLATFORM): 'time', CONF_AT: cv.time, - CONF_AFTER: cv.time, CONF_HOURS: vol.Any(vol.Coerce(int), vol.Coerce(str)), CONF_MINUTES: vol.Any(vol.Coerce(int), vol.Coerce(str)), CONF_SECONDS: vol.Any(vol.Coerce(int), vol.Coerce(str)), -}), cv.has_at_least_one_key(CONF_HOURS, CONF_MINUTES, - CONF_SECONDS, CONF_AT, CONF_AFTER)) +}), cv.has_at_least_one_key(CONF_HOURS, CONF_MINUTES, CONF_SECONDS, CONF_AT)) @asyncio.coroutine @@ -37,11 +35,6 @@ def async_trigger(hass, config, action): if CONF_AT in config: at_time = config.get(CONF_AT) hours, minutes, seconds = at_time.hour, at_time.minute, at_time.second - elif CONF_AFTER in config: - _LOGGER.warning("'after' is deprecated for the time trigger. Please " - "rename 'after' to 'at' in your configuration file.") - at_time = config.get(CONF_AFTER) - hours, minutes, seconds = at_time.hour, at_time.minute, at_time.second else: hours = config.get(CONF_HOURS) minutes = config.get(CONF_MINUTES) diff --git a/tests/components/automation/test_state.py b/tests/components/automation/test_state.py index 28473511e29..2fd6c8415db 100644 --- a/tests/components/automation/test_state.py +++ b/tests/components/automation/test_state.py @@ -130,25 +130,6 @@ class TestAutomationState(unittest.TestCase): self.hass.block_till_done() self.assertEqual(1, len(self.calls)) - def test_if_fires_on_entity_change_with_state_filter(self): - """Test for firing on entity change with state filter.""" - assert setup_component(self.hass, automation.DOMAIN, { - automation.DOMAIN: { - 'trigger': { - 'platform': 'state', - 'entity_id': 'test.entity', - 'state': 'world' - }, - 'action': { - 'service': 'test.automation' - } - } - }) - - self.hass.states.set('test.entity', 'world') - self.hass.block_till_done() - self.assertEqual(1, len(self.calls)) - def test_if_fires_on_entity_change_with_both_filters(self): """Test for firing if both filters are a non match.""" assert setup_component(self.hass, automation.DOMAIN, { From fde4a7d029bd5983ae6dbb9541082c5a88cd82e3 Mon Sep 17 00:00:00 2001 From: Jan Losinski Date: Mon, 17 Jul 2017 22:50:55 +0200 Subject: [PATCH 027/118] Citybikes: Allow None as result for empty slots (#8528) The citibykes API returns "null" as value for empty_slots on some stations (see #8527). This causes the component to not process the data. This is fixed by accepting None as valid data. The row in the frontend is left empty if "null" was returned by the service. fixes #8527 --- homeassistant/components/sensor/citybikes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/citybikes.py b/homeassistant/components/sensor/citybikes.py index 15046897732..4cb532d26eb 100644 --- a/homeassistant/components/sensor/citybikes.py +++ b/homeassistant/components/sensor/citybikes.py @@ -82,7 +82,7 @@ NETWORKS_RESPONSE_SCHEMA = vol.Schema({ STATION_SCHEMA = vol.Schema({ vol.Required(ATTR_FREE_BIKES): cv.positive_int, - vol.Required(ATTR_EMPTY_SLOTS): cv.positive_int, + vol.Required(ATTR_EMPTY_SLOTS): vol.Any(cv.positive_int, None), vol.Required(ATTR_LATITUDE): cv.latitude, vol.Required(ATTR_LONGITUDE): cv.latitude, vol.Required(ATTR_ID): cv.string, From dcd6f7a29e96d2335c8f0c19774b78697e2fe7af Mon Sep 17 00:00:00 2001 From: Phil Lavin Date: Mon, 17 Jul 2017 22:34:38 +0100 Subject: [PATCH 028/118] Return a 0 temperature value when none is found (#8518) * Return a 0 temperature value when none is found It's well documented that these TRVs will only return the current temperature for a short time after the actuator has moved. This means that, usually, they will not return the current temperature. Setting a non-value here causes errors in the logs and for the TRV to not show on the dashboard at all * Fix lint issue --- homeassistant/components/climate/maxcube.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homeassistant/components/climate/maxcube.py b/homeassistant/components/climate/maxcube.py index 9d6c1bbab5b..271616daf8b 100644 --- a/homeassistant/components/climate/maxcube.py +++ b/homeassistant/components/climate/maxcube.py @@ -10,7 +10,6 @@ import logging from homeassistant.components.climate import ClimateDevice, STATE_AUTO from homeassistant.components.maxcube import MAXCUBE_HANDLE from homeassistant.const import TEMP_CELSIUS, ATTR_TEMPERATURE -from homeassistant.const import STATE_UNKNOWN _LOGGER = logging.getLogger(__name__) @@ -140,7 +139,7 @@ class MaxCubeClimate(ClimateDevice): def map_temperature_max_hass(temperature): """Map Temperature from MAX! to HASS.""" if temperature is None: - return STATE_UNKNOWN + return 0.0 return temperature From 4ae11c009dadfcdd9609d4e1b92441e8657fece1 Mon Sep 17 00:00:00 2001 From: Thibault Cohen Date: Tue, 18 Jul 2017 10:23:39 -0400 Subject: [PATCH 029/118] Fix #6469 and #6828 (#8537) --- homeassistant/components/sensor/hydroquebec.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/sensor/hydroquebec.py b/homeassistant/components/sensor/hydroquebec.py index 45a7b812039..884f101c033 100644 --- a/homeassistant/components/sensor/hydroquebec.py +++ b/homeassistant/components/sensor/hydroquebec.py @@ -39,21 +39,21 @@ SENSOR_TYPES = { 'balance': ['Balance', PRICE, 'mdi:square-inc-cash'], 'period_total_bill': - ['Current period bill', PRICE, 'mdi:square-inc-cash'], + ['Period total bill', PRICE, 'mdi:square-inc-cash'], 'period_length': - ['Current period length', DAYS, 'mdi:calendar-today'], + ['Period length', DAYS, 'mdi:calendar-today'], 'period_total_days': - ['Total number of days in this period', DAYS, 'mdi:calendar-today'], + ['Period total days', DAYS, 'mdi:calendar-today'], 'period_mean_daily_bill': - ['Period daily average bill', PRICE, 'mdi:square-inc-cash'], + ['Period mean daily bill', PRICE, 'mdi:square-inc-cash'], 'period_mean_daily_consumption': - ['Period daily average consumption', KILOWATT_HOUR, 'mdi:flash'], + ['Period mean daily consumption', KILOWATT_HOUR, 'mdi:flash'], 'period_total_consumption': - ['Total Consumption', KILOWATT_HOUR, 'mdi:flash'], + ['Period total consumption', KILOWATT_HOUR, 'mdi:flash'], 'period_lower_price_consumption': - ['Period Lower price consumption', KILOWATT_HOUR, 'mdi:flash'], + ['Period lower price consumption', KILOWATT_HOUR, 'mdi:flash'], 'period_higher_price_consumption': - ['Period Higher price consumption', KILOWATT_HOUR, 'mdi:flash'], + ['Period higher price consumption', KILOWATT_HOUR, 'mdi:flash'], 'yesterday_total_consumption': ['Yesterday total consumption', KILOWATT_HOUR, 'mdi:flash'], 'yesterday_lower_price_consumption': @@ -125,7 +125,6 @@ class HydroQuebecSensor(Entity): """Initialize the sensor.""" self.client_name = name self.type = sensor_type - self.entity_id = "sensor.{}_{}".format(name, sensor_type) self._name = SENSOR_TYPES[sensor_type][0] self._unit_of_measurement = SENSOR_TYPES[sensor_type][1] self._icon = SENSOR_TYPES[sensor_type][2] From 879c816f5c20681c92838ffbec33c418129a0370 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Tue, 18 Jul 2017 16:23:57 +0200 Subject: [PATCH 030/118] Update docstrings (#8536) --- homeassistant/bootstrap.py | 18 +++++----- homeassistant/config.py | 74 +++++++++++++++++++------------------- 2 files changed, 46 insertions(+), 46 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index a90a96e4fa0..7831036ff59 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -40,7 +40,7 @@ def from_config_dict(config: Dict[str, Any], skip_pip: bool=False, log_rotate_days: Any=None) \ -> Optional[core.HomeAssistant]: - """Try to configure Home Assistant from a config dict. + """Try to configure Home Assistant from a configuration dictionary. Dynamically loads required components and its dependencies. """ @@ -71,7 +71,7 @@ def async_from_config_dict(config: Dict[str, Any], skip_pip: bool=False, log_rotate_days: Any=None) \ -> Optional[core.HomeAssistant]: - """Try to configure Home Assistant from a config dict. + """Try to configure Home Assistant from a configuration dictionary. Dynamically loads required components and its dependencies. This method is a coroutine. @@ -92,8 +92,8 @@ def async_from_config_dict(config: Dict[str, Any], hass.config.skip_pip = skip_pip if skip_pip: - _LOGGER.warning('Skipping pip installation of required modules. ' - 'This may cause issues.') + _LOGGER.warning("Skipping pip installation of required modules. " + "This may cause issues") if not loader.PREPARED: yield from hass.async_add_job(loader.prepare, hass) @@ -118,13 +118,13 @@ def async_from_config_dict(config: Dict[str, Any], # pylint: disable=not-an-iterable res = yield from core_components.async_setup(hass, config) if not res: - _LOGGER.error('Home Assistant core failed to initialize. ' - 'Further initialization aborted.') + _LOGGER.error("Home Assistant core failed to initialize. " + "further initialization aborted") return hass yield from persistent_notification.async_setup(hass, config) - _LOGGER.info('Home Assistant core initialized') + _LOGGER.info("Home Assistant core initialized") # stage 1 for component in components: @@ -143,7 +143,7 @@ def async_from_config_dict(config: Dict[str, Any], yield from hass.async_block_till_done() stop = time() - _LOGGER.info('Home Assistant initialized in %.2fs', stop-start) + _LOGGER.info("Home Assistant initialized in %.2fs", stop-start) async_register_signal_handling(hass) return hass @@ -193,7 +193,7 @@ def async_from_config_file(config_path: str, config_dict = yield from hass.async_add_job( conf_util.load_yaml_config_file, config_path) except HomeAssistantError as err: - _LOGGER.error('Error loading %s: %s', config_path, err) + _LOGGER.error("Error loading %s: %s", config_path, err) return None finally: clear_secret_cache() diff --git a/homeassistant/config.py b/homeassistant/config.py index cb8d0b442c1..003e6481685 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -40,7 +40,7 @@ CONFIG_DIR_NAME = '.homeassistant' DATA_CUSTOMIZE = 'hass_customize' FILE_MIGRATION = [ - ["ios.conf", ".ios.conf"], + ['ios.conf', '.ios.conf'], ] DEFAULT_CORE_CONFIG = ( @@ -71,7 +71,7 @@ config: http: # Uncomment this to add a password (recommended!) # api_password: PASSWORD - # Uncomment this if you are using SSL or running in Docker etc + # Uncomment this if you are using SSL/TLS, running in Docker container, etc. # base_url: example.duckdns.org:8123 # Checks for available updates @@ -89,7 +89,7 @@ discovery: # Allows you to issue voice commands from the frontend in enabled browsers conversation: -# Enables support for tracking state changes over time. +# Enables support for tracking state changes over time history: # View all events in a logbook @@ -98,13 +98,13 @@ logbook: # Track the sun sun: -# Weather Prediction +# Weather prediction sensor: - platform: yr + - platform: yr # Text to speech tts: - platform: google + - platform: google group: !include groups.yaml automation: !include automations.yaml @@ -141,17 +141,17 @@ CORE_CONFIG_SCHEMA = CUSTOMIZE_CONFIG_SCHEMA.extend({ def get_default_config_dir() -> str: - """Put together the default configuration directory based on OS.""" + """Put together the default configuration directory based on the OS.""" data_dir = os.getenv('APPDATA') if os.name == "nt" \ else os.path.expanduser('~') return os.path.join(data_dir, CONFIG_DIR_NAME) def ensure_config_exists(config_dir: str, detect_location: bool=True) -> str: - """Ensure a config file exists in given configuration directory. + """Ensure a configuration file exists in given configuration directory. Creating a default one if needed. - Return path to the config file. + Return path to the configuration file. """ config_path = find_config_file(config_dir) @@ -195,8 +195,8 @@ def create_default_config(config_dir, detect_location=True): info[attr] = getattr(location_info, prop) or default if location_info.latitude and location_info.longitude: - info[CONF_ELEVATION] = loc_util.elevation(location_info.latitude, - location_info.longitude) + info[CONF_ELEVATION] = loc_util.elevation( + location_info.latitude, location_info.longitude) # Writing files with YAML does not create the most human readable results # So we're hard coding a YAML template. @@ -225,16 +225,16 @@ def create_default_config(config_dir, detect_location=True): return config_path except IOError: - print('Unable to create default configuration file', config_path) + print("Unable to create default configuration file", config_path) return None @asyncio.coroutine def async_hass_config_yaml(hass): - """Load YAML from hass config File. + """Load YAML from a Home Assistant configuration file. - This function allow component inside asyncio loop to reload his config by - self. + This function allow a component inside the asyncio loop to reload its + configuration by itself. This method is a coroutine. """ @@ -269,7 +269,7 @@ def load_yaml_config_file(config_path): getattr(err, 'filename', err))) if not isinstance(conf_dict, dict): - msg = 'The configuration file {} does not contain a dictionary'.format( + msg = "The configuration file {} does not contain a dictionary".format( os.path.basename(config_path)) _LOGGER.error(msg) raise HomeAssistantError(msg) @@ -278,7 +278,7 @@ def load_yaml_config_file(config_path): def process_ha_config_upgrade(hass): - """Upgrade config if necessary. + """Upgrade configuration if necessary. This method needs to run in an executor. """ @@ -294,8 +294,8 @@ def process_ha_config_upgrade(hass): if conf_version == __version__: return - _LOGGER.info('Upgrading config directory from %s to %s', conf_version, - __version__) + _LOGGER.info("Upgrading configuration directory from %s to %s", + conf_version, __version__) if LooseVersion(conf_version) < LooseVersion('0.49'): # 0.49 introduced persistent deps dir. @@ -306,20 +306,20 @@ def process_ha_config_upgrade(hass): with open(version_path, 'wt') as outp: outp.write(__version__) - _LOGGER.info('Migrating old system config files to new locations') + _LOGGER.info("Migrating old system configuration files to new locations") for oldf, newf in FILE_MIGRATION: if os.path.isfile(hass.config.path(oldf)): - _LOGGER.info('Migrating %s to %s', oldf, newf) + _LOGGER.info("Migrating %s to %s", oldf, newf) os.rename(hass.config.path(oldf), hass.config.path(newf)) @callback def async_log_exception(ex, domain, config, hass): - """Generate log exception for config validation. + """Generate log exception for configuration validation. This method must be run in the event loop. """ - message = 'Invalid config for [{}]: '.format(domain) + message = "Invalid config for [{}]: ".format(domain) if hass is not None: async_notify_setup_error(hass, domain, True) @@ -344,7 +344,7 @@ def async_log_exception(ex, domain, config, hass): @asyncio.coroutine def async_process_ha_core_config(hass, config): - """Process the [homeassistant] section from the config. + """Process the [homeassistant] section from the configuration. This method is a coroutine. """ @@ -362,7 +362,7 @@ def async_process_ha_core_config(hass, config): hac.time_zone = time_zone date_util.set_default_time_zone(time_zone) else: - _LOGGER.error('Received invalid time zone %s', time_zone_str) + _LOGGER.error("Received invalid time zone %s", time_zone_str) for key, attr in ((CONF_LATITUDE, 'latitude'), (CONF_LONGITUDE, 'longitude'), @@ -374,7 +374,7 @@ def async_process_ha_core_config(hass, config): if CONF_TIME_ZONE in config: set_time_zone(config.get(CONF_TIME_ZONE)) - # init whitelist external dir + # Init whitelist external dir hac.whitelist_external_dirs = set((hass.config.path('www'),)) if CONF_WHITELIST_EXTERNAL_DIRS in config: hac.whitelist_external_dirs.update( @@ -394,7 +394,7 @@ def async_process_ha_core_config(hass, config): try: pkg_cust = CUSTOMIZE_CONFIG_SCHEMA(pkg_cust) except vol.Invalid: - _LOGGER.warning('Package %s contains invalid customize', name) + _LOGGER.warning("Package %s contains invalid customize", name) continue cust_exact.update(pkg_cust[CONF_CUSTOMIZE]) @@ -415,9 +415,9 @@ def async_process_ha_core_config(hass, config): hac.units = METRIC_SYSTEM else: hac.units = IMPERIAL_SYSTEM - _LOGGER.warning("Found deprecated temperature unit in core config, " - "expected unit system. Replace '%s: %s' with " - "'%s: %s'", CONF_TEMPERATURE_UNIT, unit, + _LOGGER.warning("Found deprecated temperature unit in core " + "configuration expected unit system. Replace '%s: %s' " + "with '%s: %s'", CONF_TEMPERATURE_UNIT, unit, CONF_UNIT_SYSTEM, hac.units.name) # Shortcut if no auto-detection necessary @@ -434,7 +434,7 @@ def async_process_ha_core_config(hass, config): loc_util.detect_location_info) if info is None: - _LOGGER.error('Could not detect location information') + _LOGGER.error("Could not detect location information") return if hac.latitude is None and hac.longitude is None: @@ -463,8 +463,8 @@ def async_process_ha_core_config(hass, config): if discovered: _LOGGER.warning( - 'Incomplete core config. Auto detected %s', - ', '.join('{}: {}'.format(key, val) for key, val in discovered)) + "Incomplete core configuration. Auto detected %s", + ", ".join('{}: {}'.format(key, val) for key, val in discovered)) def _log_pkg_error(package, component, config, message): @@ -495,7 +495,7 @@ def _identify_config_schema(module): def merge_packages_config(config, packages): - """Merge packages into the top-level config. Mutate config.""" + """Merge packages into the top-level configuration. Mutate config.""" # pylint: disable=too-many-nested-blocks PACKAGES_CONFIG_SCHEMA(packages) for pack_name, pack_conf in packages.items(): @@ -549,7 +549,7 @@ def merge_packages_config(config, packages): if comp_name in config: _log_pkg_error( pack_name, comp_name, config, "may occur only once" - " and it already exist in your main config") + " and it already exist in your main configuration") continue config[comp_name] = comp_conf @@ -558,7 +558,7 @@ def merge_packages_config(config, packages): @callback def async_process_component_config(hass, config, domain): - """Check component config and return processed config. + """Check component configuration and return processed configuration. Raise a vol.Invalid exception on error. @@ -619,7 +619,7 @@ def async_process_component_config(hass, config, domain): @asyncio.coroutine def async_check_ha_config_file(hass): - """Check if HA config file valid. + """Check if Home Assistant configuration file is valid. This method is a coroutine. """ From 2aa89cfe07792dabc18e4888aa6ba16c59e287cf Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Tue, 18 Jul 2017 16:24:32 +0200 Subject: [PATCH 031/118] Upgrade TwitterAPI to 2.4.6 (#8535) --- homeassistant/components/notify/twitter.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/notify/twitter.py b/homeassistant/components/notify/twitter.py index 74002b89c76..9d2a8c07932 100644 --- a/homeassistant/components/notify/twitter.py +++ b/homeassistant/components/notify/twitter.py @@ -16,7 +16,7 @@ from homeassistant.components.notify import ( ATTR_DATA, PLATFORM_SCHEMA, BaseNotificationService) from homeassistant.const import CONF_ACCESS_TOKEN, CONF_USERNAME -REQUIREMENTS = ['TwitterAPI==2.4.5'] +REQUIREMENTS = ['TwitterAPI==2.4.6'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index e07cc8de84c..5cb1e676b27 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -36,7 +36,7 @@ PyMata==2.14 SoCo==0.12 # homeassistant.components.notify.twitter -TwitterAPI==2.4.5 +TwitterAPI==2.4.6 # homeassistant.components.device_tracker.automatic aioautomatic==0.4.0 From 29266213a0ea0c9b21a167f40b9f1f7e31f0ef8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre=20St=C3=A5hl?= Date: Tue, 18 Jul 2017 20:19:36 +0200 Subject: [PATCH 032/118] Fix support for multiple Apple TVs (#8539) --- homeassistant/components/apple_tv.py | 2 +- homeassistant/components/remote/apple_tv.py | 5 +++++ requirements_all.txt | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/apple_tv.py b/homeassistant/components/apple_tv.py index 948caa27538..c5f40ca5db8 100644 --- a/homeassistant/components/apple_tv.py +++ b/homeassistant/components/apple_tv.py @@ -17,7 +17,7 @@ from homeassistant.helpers import discovery from homeassistant.components.discovery import SERVICE_APPLE_TV import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['pyatv==0.3.2'] +REQUIREMENTS = ['pyatv==0.3.4'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/remote/apple_tv.py b/homeassistant/components/remote/apple_tv.py index a7ea113c2db..e89234c60ac 100644 --- a/homeassistant/components/remote/apple_tv.py +++ b/homeassistant/components/remote/apple_tv.py @@ -44,6 +44,11 @@ class AppleTVRemote(remote.RemoteDevice): """Return the name of the device.""" return self._name + @property + def unique_id(self): + """Return an unique ID.""" + return self._atv.metadata.device_id + @property def is_on(self): """Return true if device is on.""" diff --git a/requirements_all.txt b/requirements_all.txt index 5cb1e676b27..0eccc3c0aa2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -519,7 +519,7 @@ pyasn1-modules==0.0.9 pyasn1==0.2.3 # homeassistant.components.apple_tv -pyatv==0.3.2 +pyatv==0.3.4 # homeassistant.components.device_tracker.bbox # homeassistant.components.sensor.bbox From 5e1ff20b09cd38ba7fa47b39d3ac9f2440628591 Mon Sep 17 00:00:00 2001 From: Thibault Cohen Date: Tue, 18 Jul 2017 18:02:42 -0400 Subject: [PATCH 033/118] Decora: Fix set brightness and improve reconnection (#8522) --- homeassistant/components/light/decora.py | 10 +++++++--- requirements_all.txt | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/light/decora.py b/homeassistant/components/light/decora.py index bc45870f5f2..17cc741c593 100644 --- a/homeassistant/components/light/decora.py +++ b/homeassistant/components/light/decora.py @@ -16,7 +16,7 @@ from homeassistant.components.light import ( PLATFORM_SCHEMA) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['decora==0.6'] +REQUIREMENTS = ['decora==0.6', 'bluepy==1.1.1'] _LOGGER = logging.getLogger(__name__) @@ -39,6 +39,7 @@ def retry(method): """Try send command and retry on error.""" # pylint: disable=import-error import decora + import bluepy initial = time.monotonic() while True: @@ -46,7 +47,10 @@ def retry(method): return None try: return method(device, *args, **kwds) - except (decora.decoraException, AttributeError): + except (decora.decoraException, AttributeError, + bluepy.btle.BTLEException): + _LOGGER.warning("Decora connect error for device %s. " + "Reconnecting...", device.name) # pylint: disable=protected-access device._switch.connect() return wrapper_retry @@ -119,7 +123,7 @@ class DecoraLight(Light): @retry def set_state(self, brightness): """Set the state of this lamp to the provided brightness.""" - self._switch.set_brightness(brightness / 2.55) + self._switch.set_brightness(int(brightness / 2.55)) self._brightness = brightness @retry diff --git a/requirements_all.txt b/requirements_all.txt index 0eccc3c0aa2..c11959387b1 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -106,6 +106,9 @@ blinkstick==1.1.8 # homeassistant.components.sensor.bitcoin blockchain==1.3.3 +# homeassistant.components.light.decora +# bluepy==1.1.1 + # homeassistant.components.notify.aws_lambda # homeassistant.components.notify.aws_sns # homeassistant.components.notify.aws_sqs From d54a634f112f347262ef342e2d3e21c5f6eb4b8e Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 18 Jul 2017 15:11:17 -0700 Subject: [PATCH 034/118] Update demo.py --- homeassistant/components/demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/demo.py b/homeassistant/components/demo.py index 27bb1bbb8d1..187e899aacd 100644 --- a/homeassistant/components/demo.py +++ b/homeassistant/components/demo.py @@ -107,7 +107,7 @@ def async_setup(hass, config): # Set up example persistent notification persistent_notification.async_create( - hass, 'This is an example of a persistent notification.', + 'This is an example of a persistent notification.', title='Example Notification') # Set up room groups From 1a86fa5a02e950d36f8e5c8474f47ccd53816926 Mon Sep 17 00:00:00 2001 From: Kevin Fronczak Date: Tue, 18 Jul 2017 18:16:32 -0400 Subject: [PATCH 035/118] Initial support for Google Wifi/OnHub (#8485) * Initial support for Google Wifi/OnHub * Moved state logic to update function of API class - Throttle added to update - State logic implementation is cleaner - Modified tests to work with the new throttle on update --- .../components/sensor/google_wifi.py | 201 +++++++++++++++++ tests/components/sensor/test_google_wifi.py | 203 ++++++++++++++++++ 2 files changed, 404 insertions(+) create mode 100644 homeassistant/components/sensor/google_wifi.py create mode 100644 tests/components/sensor/test_google_wifi.py diff --git a/homeassistant/components/sensor/google_wifi.py b/homeassistant/components/sensor/google_wifi.py new file mode 100644 index 00000000000..d878f4f8d20 --- /dev/null +++ b/homeassistant/components/sensor/google_wifi.py @@ -0,0 +1,201 @@ +""" +Support for retreiving status info from Google Wifi/OnHub routers. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.google_wifi/ +""" +import logging +from datetime import timedelta + +import voluptuous as vol +import requests + +import homeassistant.util.dt as dt +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity import Entity +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.util import Throttle +from homeassistant.const import ( + CONF_NAME, CONF_HOST, CONF_MONITORED_CONDITIONS, + STATE_UNKNOWN) + +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=1) + +_LOGGER = logging.getLogger(__name__) + +ENDPOINT = '/api/v1/status' + +ATTR_CURRENT_VERSION = 'current_version' +ATTR_NEW_VERSION = 'new_version' +ATTR_UPTIME = 'uptime' +ATTR_LAST_RESTART = 'last_restart' +ATTR_LOCAL_IP = 'local_ip' +ATTR_STATUS = 'status' + +DEFAULT_NAME = 'google_wifi' +DEFAULT_HOST = 'testwifi.here' + +MONITORED_CONDITIONS = { + ATTR_CURRENT_VERSION: [ + 'Current Version', + None, + 'mdi:checkbox-marked-circle-outline' + ], + ATTR_NEW_VERSION: [ + 'New Version', + None, + 'mdi:update' + ], + ATTR_UPTIME: [ + 'Uptime', + 'days', + 'mdi:timelapse' + ], + ATTR_LAST_RESTART: [ + 'Last Network Restart', + None, + 'mdi:restart' + ], + ATTR_LOCAL_IP: [ + 'Local IP Address', + None, + 'mdi:access-point-network' + ], + ATTR_STATUS: [ + 'Status', + None, + 'mdi:google' + ] +} + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, + vol.Optional(CONF_MONITORED_CONDITIONS, default=MONITORED_CONDITIONS): + vol.All(cv.ensure_list, [vol.In(MONITORED_CONDITIONS)]), +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the Google Wifi sensor.""" + name = config.get(CONF_NAME) + host = config.get(CONF_HOST) + + api = GoogleWifiAPI(host) + + sensors = [GoogleWifiSensor(hass, api, name, condition) + for condition in config[CONF_MONITORED_CONDITIONS]] + + add_devices(sensors, True) + + +class GoogleWifiSensor(Entity): + """Representation of a Google Wifi sensor.""" + + def __init__(self, hass, api, name, variable): + """Initialize a Pi-Hole sensor.""" + self._hass = hass + self._api = api + self._name = name + self._state = STATE_UNKNOWN + + variable_info = MONITORED_CONDITIONS[variable] + self._var_name = variable + self._var_units = variable_info[1] + self._var_icon = variable_info[2] + + @property + def name(self): + """Return the name of the sensor.""" + return "{}_{}".format(self._name, self._var_name) + + @property + def icon(self): + """Icon to use in the frontend, if any.""" + return self._var_icon + + @property + def unit_of_measurement(self): + """Return the unit the value is expressed in.""" + return self._var_units + + @property + def availiable(self): + """Return availiability of goole wifi api.""" + return self._api.availiable + + @property + def state(self): + """Return the state of the device.""" + return self._state + + def update(self): + """Get the latest data from the Google Wifi API.""" + self._api.update() + if self.availiable: + self._state = self._api.data[self._var_name] + else: + self._state = STATE_UNKNOWN + + +class GoogleWifiAPI(object): + """Get the latest data and update the states.""" + + def __init__(self, host): + """Initialize the data object.""" + uri = 'http://' + resource = "{}{}{}".format(uri, host, ENDPOINT) + + self._request = requests.Request('GET', resource).prepare() + self.raw_data = None + self.data = { + ATTR_CURRENT_VERSION: STATE_UNKNOWN, + ATTR_NEW_VERSION: STATE_UNKNOWN, + ATTR_UPTIME: STATE_UNKNOWN, + ATTR_LAST_RESTART: STATE_UNKNOWN, + ATTR_LOCAL_IP: STATE_UNKNOWN, + ATTR_STATUS: STATE_UNKNOWN + } + self.availiable = True + self.update() + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Get the latest data from the router.""" + try: + _LOGGER.error("Before request") + with requests.Session() as sess: + response = sess.send( + self._request, timeout=10) + self.raw_data = response.json() + _LOGGER.error(self.raw_data) + self.data_format() + self.availiable = True + except ValueError: + _LOGGER.error("Unable to fetch data from Google Wifi") + self.availiable = False + self.raw_data = None + + def data_format(self): + """Format raw data into easily accessible dict.""" + for key, value in self.raw_data.items(): + if key == 'software': + self.data[ATTR_CURRENT_VERSION] = value['softwareVersion'] + if value['updateNewVersion'] == '0.0.0.0': + self.data[ATTR_NEW_VERSION] = 'Latest' + else: + self.data[ATTR_NEW_VERSION] = value['updateNewVersion'] + elif key == 'system': + self.data[ATTR_UPTIME] = value['uptime'] / (3600 * 24) + last_restart = dt.now() - timedelta(seconds=value['uptime']) + self.data[ATTR_LAST_RESTART] = \ + last_restart.strftime("%Y-%m-%d %H:%M:%S") + elif key == 'wan': + if value['online']: + self.data[ATTR_STATUS] = 'Online' + else: + self.data[ATTR_STATUS] = 'Offline' + if not value['ipAddress']: + self.data[ATTR_LOCAL_IP] = STATE_UNKNOWN + else: + self.data[ATTR_LOCAL_IP] = value['localIpAddress'] diff --git a/tests/components/sensor/test_google_wifi.py b/tests/components/sensor/test_google_wifi.py new file mode 100644 index 00000000000..978ec99236c --- /dev/null +++ b/tests/components/sensor/test_google_wifi.py @@ -0,0 +1,203 @@ +"""The tests for the Google Wifi platform.""" +import unittest +from unittest.mock import patch, Mock +from datetime import datetime, timedelta +import requests_mock + +from homeassistant import core as ha +from homeassistant.setup import setup_component +import homeassistant.components.sensor.google_wifi as google_wifi +from homeassistant.const import STATE_UNKNOWN +from homeassistant.util import dt as dt_util + +from tests.common import get_test_home_assistant, assert_setup_component + +NAME = 'foo' + +MOCK_DATA = ('{"software": {"softwareVersion":"initial",' + '"updateNewVersion":"initial"},' + '"system": {"uptime":86400},' + '"wan": {"localIpAddress":"initial", "online":true,' + '"ipAddress":true}}') + +MOCK_DATA_NEXT = ('{"software": {"softwareVersion":"next",' + '"updateNewVersion":"0.0.0.0"},' + '"system": {"uptime":172800},' + '"wan": {"localIpAddress":"next", "online":false,' + '"ipAddress":false}}') + + +class TestGoogleWifiSetup(unittest.TestCase): + """Tests for setting up the Google Wifi switch platform.""" + + def setUp(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + + def tearDown(self): + """Stop everything that was started.""" + self.hass.stop() + + @requests_mock.Mocker() + def test_setup_minimum(self, mock_req): + """Test setup with minimum configuration.""" + resource = '{}{}{}'.format('http://', + google_wifi.DEFAULT_HOST, + google_wifi.ENDPOINT) + mock_req.get(resource, status_code=200) + self.assertTrue(setup_component(self.hass, 'sensor', { + 'sensor': { + 'platform': 'google_wifi' + } + })) + + @requests_mock.Mocker() + def test_setup_get(self, mock_req): + """Test setup with full configuration.""" + resource = '{}{}{}'.format('http://', + 'localhost', + google_wifi.ENDPOINT) + mock_req.get(resource, status_code=200) + self.assertTrue(setup_component(self.hass, 'sensor', { + 'sensor': { + 'platform': 'google_wifi', + 'host': 'localhost', + 'name': 'Test Wifi', + 'monitored_conditions': ['current_version', + 'new_version', + 'uptime', + 'last_restart', + 'local_ip', + 'status'] + } + })) + assert_setup_component(6, 'sensor') + + +class TestGoogleWifiSensor(unittest.TestCase): + """Tests for Google Wifi sensor platform.""" + + def setUp(self): + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + with requests_mock.Mocker() as mock_req: + self.setup_api(MOCK_DATA, mock_req) + + def tearDown(self): + """Stop everything that was started.""" + self.hass.stop() + + def setup_api(self, data, mock_req): + """Setup API with fake data.""" + resource = '{}{}{}'.format('http://', + 'localhost', + google_wifi.ENDPOINT) + now = datetime(1970, month=1, day=1) + with patch('homeassistant.util.dt.now', return_value=now): + mock_req.get(resource, text=data, status_code=200) + self.api = google_wifi.GoogleWifiAPI("localhost") + self.name = NAME + self.sensor_dict = dict() + for condition, cond_list in google_wifi.MONITORED_CONDITIONS.items(): + sensor = google_wifi.GoogleWifiSensor(self.hass, self.api, + self.name, condition) + name = '{}_{}'.format(self.name, condition) + units = cond_list[1] + icon = cond_list[2] + self.sensor_dict[condition] = {'sensor': sensor, + 'name': name, + 'units': units, + 'icon': icon} + + def fake_delay(self, ha_delay): + """Fake delay to prevent update throttle.""" + hass_now = dt_util.utcnow() + shifted_time = hass_now + timedelta(seconds=ha_delay) + self.hass.bus.fire(ha.EVENT_TIME_CHANGED, + {ha.ATTR_NOW: shifted_time}) + + def test_name(self): + """Test the name.""" + for name in self.sensor_dict: + sensor = self.sensor_dict[name]['sensor'] + test_name = self.sensor_dict[name]['name'] + self.assertEqual(test_name, sensor.name) + + def test_unit_of_measurement(self): + """Test the unit of measurement.""" + for name in self.sensor_dict: + sensor = self.sensor_dict[name]['sensor'] + self.assertEqual(self.sensor_dict[name]['units'], + sensor.unit_of_measurement) + + def test_icon(self): + """Test the icon.""" + for name in self.sensor_dict: + sensor = self.sensor_dict[name]['sensor'] + self.assertEqual(self.sensor_dict[name]['icon'], sensor.icon) + + @requests_mock.Mocker() + def test_state(self, mock_req): + """Test the initial state.""" + self.setup_api(MOCK_DATA, mock_req) + now = datetime(1970, month=1, day=1) + with patch('homeassistant.util.dt.now', return_value=now): + for name in self.sensor_dict: + sensor = self.sensor_dict[name]['sensor'] + self.fake_delay(2) + sensor.update() + if name == google_wifi.ATTR_LAST_RESTART: + self.assertEqual('1969-12-31 00:00:00', sensor.state) + elif name == google_wifi.ATTR_UPTIME: + self.assertEqual(1, sensor.state) + elif name == google_wifi.ATTR_STATUS: + self.assertEqual('Online', sensor.state) + else: + self.assertEqual('initial', sensor.state) + + @requests_mock.Mocker() + def test_update_when_value_is_none(self, mock_req): + """Test state gets updated to unknown when sensor returns no data.""" + self.setup_api(None, mock_req) + for name in self.sensor_dict: + sensor = self.sensor_dict[name]['sensor'] + self.fake_delay(2) + sensor.update() + self.assertEqual(STATE_UNKNOWN, sensor.state) + + @requests_mock.Mocker() + def test_update_when_value_changed(self, mock_req): + """Test state gets updated when sensor returns a new status.""" + self.setup_api(MOCK_DATA_NEXT, mock_req) + now = datetime(1970, month=1, day=1) + with patch('homeassistant.util.dt.now', return_value=now): + for name in self.sensor_dict: + sensor = self.sensor_dict[name]['sensor'] + self.fake_delay(2) + sensor.update() + if name == google_wifi.ATTR_LAST_RESTART: + self.assertEqual('1969-12-30 00:00:00', sensor.state) + elif name == google_wifi.ATTR_UPTIME: + self.assertEqual(2, sensor.state) + elif name == google_wifi.ATTR_STATUS: + self.assertEqual('Offline', sensor.state) + elif name == google_wifi.ATTR_NEW_VERSION: + self.assertEqual('Latest', sensor.state) + elif name == google_wifi.ATTR_LOCAL_IP: + self.assertEqual(STATE_UNKNOWN, sensor.state) + else: + self.assertEqual('next', sensor.state) + + def test_update_when_unavailiable(self): + """Test state updates when Google Wifi unavailiable.""" + self.api.update = Mock('google_wifi.GoogleWifiAPI.update', + side_effect=self.update_side_effect()) + for name in self.sensor_dict: + sensor = self.sensor_dict[name]['sensor'] + sensor.update() + self.assertEqual(STATE_UNKNOWN, sensor.state) + + def update_side_effect(self): + """Mock representation of update function.""" + self.api.data = None + self.api.availiable = False From 4ece4bf241629189eb911a390208b7e24af5110b Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Wed, 19 Jul 2017 03:04:01 -0400 Subject: [PATCH 036/118] Fix exception dlib_face_identify when image is not recognized by face_recognition module (#8552) * Some images are not supported by face_recognition, so this patch treats the error messages instead throwing a traceback. Fixes #7867 * Makes lint happy --- .../components/image_processing/dlib_face_identify.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/image_processing/dlib_face_identify.py b/homeassistant/components/image_processing/dlib_face_identify.py index 8df6de91da4..ec98d5bdcff 100644 --- a/homeassistant/components/image_processing/dlib_face_identify.py +++ b/homeassistant/components/image_processing/dlib_face_identify.py @@ -58,8 +58,12 @@ class DlibFaceIdentifyEntity(ImageProcessingFaceEntity): self._faces = {} for face_name, face_file in faces.items(): - image = face_recognition.load_image_file(face_file) - self._faces[face_name] = face_recognition.face_encodings(image)[0] + try: + image = face_recognition.load_image_file(face_file) + self._faces[face_name] = \ + face_recognition.face_encodings(image)[0] + except IndexError as err: + _LOGGER.error("Failed to parse %s. Error: %s", face_file, err) @property def camera_entity(self): From 6bc07298d3131c9aa10c9513b04a9020eaa14eb1 Mon Sep 17 00:00:00 2001 From: Aliaksandr Date: Wed, 19 Jul 2017 10:14:48 +0300 Subject: [PATCH 037/118] [media_extractor] Add support for custom stream queries for media_extractor (#8538) * Add support for different stream formats * Encapsulate logic inside MediaExtractor class * Add CONFIG_SCHEMA * Fix for cases when youtube-dl returns content of playlist as list --- homeassistant/components/media_extractor.py | 190 ++++++++++++++------ 1 file changed, 139 insertions(+), 51 deletions(-) diff --git a/homeassistant/components/media_extractor.py b/homeassistant/components/media_extractor.py index c7d019973a3..559af46e9f6 100644 --- a/homeassistant/components/media_extractor.py +++ b/homeassistant/components/media_extractor.py @@ -6,11 +6,14 @@ https://home-assistant.io/components/media_extractor/ """ import logging import os +import voluptuous as vol from homeassistant.components.media_player import ( - ATTR_MEDIA_CONTENT_ID, DOMAIN as MEDIA_PLAYER_DOMAIN, - MEDIA_PLAYER_PLAY_MEDIA_SCHEMA, SERVICE_PLAY_MEDIA) + ATTR_ENTITY_ID, ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_CONTENT_TYPE, + DOMAIN as MEDIA_PLAYER_DOMAIN, MEDIA_PLAYER_PLAY_MEDIA_SCHEMA, + SERVICE_PLAY_MEDIA) from homeassistant.config import load_yaml_config_file +from homeassistant.helpers import config_validation as cv REQUIREMENTS = ['youtube_dl==2017.7.9'] @@ -19,6 +22,18 @@ _LOGGER = logging.getLogger(__name__) DOMAIN = 'media_extractor' DEPENDENCIES = ['media_player'] +CONF_CUSTOMIZE_ENTITIES = 'customize' +CONF_DEFAULT_STREAM_QUERY = 'default_query' +DEFAULT_STREAM_QUERY = 'best' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Optional(CONF_DEFAULT_STREAM_QUERY): cv.string, + vol.Optional(CONF_CUSTOMIZE_ENTITIES): + vol.Schema({cv.entity_id: vol.Schema({cv.string: cv.string})}), + }), +}, extra=vol.ALLOW_EXTRA) + def setup(hass, config): """Set up the media extractor service.""" @@ -28,23 +43,7 @@ def setup(hass, config): def play_media(call): """Get stream URL and send it to the media_player.play_media.""" - media_url = call.data.get(ATTR_MEDIA_CONTENT_ID) - - try: - stream_url = get_media_stream_url(media_url) - except YDException: - _LOGGER.error("Could not retrieve data for the URL: %s", - media_url) - return - else: - data = {k: v for k, v in call.data.items() - if k != ATTR_MEDIA_CONTENT_ID} - data[ATTR_MEDIA_CONTENT_ID] = stream_url - - hass.async_add_job( - hass.services.async_call( - MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, data) - ) + MediaExtractor(hass, config[DOMAIN], call.data).extract_and_send() hass.services.register(DOMAIN, SERVICE_PLAY_MEDIA, @@ -55,47 +54,136 @@ def setup(hass, config): return True -class YDException(Exception): - """General service exception.""" +class MEDownloadException(Exception): + """Media extractor download exception.""" pass -def get_media_stream_url(media_url): - """Extract stream URL from the media URL.""" - from youtube_dl import YoutubeDL - from youtube_dl.utils import DownloadError, ExtractorError +class MEQueryException(Exception): + """Media extractor query exception.""" - ydl = YoutubeDL({'quiet': True, 'logger': _LOGGER}) + pass - try: - all_media_streams = ydl.extract_info(media_url, process=False) - except DownloadError: - # This exception will be logged by youtube-dl itself - raise YDException() - if 'entries' in all_media_streams: - _LOGGER.warning("Playlists are not supported, " - "looking for the first video") +class MediaExtractor: + """Class which encapsulates all extraction logic.""" + + def __init__(self, hass, component_config, call_data): + """Initialize media extractor.""" + self.hass = hass + self.config = component_config + self.call_data = call_data + + def get_media_url(self): + """Return media content url.""" + return self.call_data.get(ATTR_MEDIA_CONTENT_ID) + + def get_entities(self): + """Return list of entities.""" + return self.call_data.get(ATTR_ENTITY_ID, []) + + def extract_and_send(self): + """Extract exact stream format for each entity_id and play it.""" try: - selected_stream = next(all_media_streams['entries']) - except StopIteration: - _LOGGER.error("Playlist is empty") - raise YDException() - else: - selected_stream = all_media_streams + stream_selector = self.get_stream_selector() + except MEDownloadException: + _LOGGER.error("Could not retrieve data for the URL: %s", + self.get_media_url()) + else: + entities = self.get_entities() - try: - media_info = ydl.process_ie_result(selected_stream, download=False) - except (ExtractorError, DownloadError): - # This exception will be logged by youtube-dl itself - raise YDException() + if len(entities) == 0: + self.call_media_player_service(stream_selector, None) - format_selector = ydl.build_format_selector('best') + for entity_id in entities: + self.call_media_player_service(stream_selector, entity_id) - try: - best_quality_stream = next(format_selector(media_info)) - except (KeyError, StopIteration): - best_quality_stream = media_info + def get_stream_selector(self): + """Return format selector for the media URL.""" + from youtube_dl import YoutubeDL + from youtube_dl.utils import DownloadError, ExtractorError - return best_quality_stream['url'] + ydl = YoutubeDL({'quiet': True, 'logger': _LOGGER}) + + try: + all_media = ydl.extract_info(self.get_media_url(), + process=False) + except DownloadError: + # This exception will be logged by youtube-dl itself + raise MEDownloadException() + + if 'entries' in all_media: + _LOGGER.warning("Playlists are not supported, " + "looking for the first video") + entries = list(all_media['entries']) + if len(entries) > 0: + selected_media = entries[0] + else: + _LOGGER.error("Playlist is empty") + raise MEDownloadException() + else: + selected_media = all_media + + try: + media_info = ydl.process_ie_result(selected_media, + download=False) + except (ExtractorError, DownloadError): + # This exception will be logged by youtube-dl itself + raise MEDownloadException() + + def stream_selector(query): + """Find stream url that matches query.""" + try: + format_selector = ydl.build_format_selector(query) + except (SyntaxError, ValueError, AttributeError) as ex: + _LOGGER.error(ex) + raise MEQueryException() + + try: + requested_stream = next(format_selector(media_info)) + except (KeyError, StopIteration): + _LOGGER.error("Could not extract stream for the query: %s", + query) + raise MEQueryException() + + return requested_stream['url'] + + return stream_selector + + def call_media_player_service(self, stream_selector, entity_id): + """Call media_player.play_media service.""" + stream_query = self.get_stream_query_for_entity(entity_id) + + try: + stream_url = stream_selector(stream_query) + except MEQueryException: + _LOGGER.error("Wrong query format: %s", stream_query) + return + else: + data = {k: v for k, v in self.call_data.items() + if k != ATTR_ENTITY_ID} + data[ATTR_MEDIA_CONTENT_ID] = stream_url + + if entity_id: + data[ATTR_ENTITY_ID] = entity_id + + self.hass.async_add_job( + self.hass.services.async_call( + MEDIA_PLAYER_DOMAIN, SERVICE_PLAY_MEDIA, data) + ) + + def get_stream_query_for_entity(self, entity_id): + """Get stream format query for entity.""" + default_stream_query = self.config.get(CONF_DEFAULT_STREAM_QUERY, + DEFAULT_STREAM_QUERY) + + if entity_id: + media_content_type = self.call_data.get(ATTR_MEDIA_CONTENT_TYPE) + + return self.config \ + .get(CONF_CUSTOMIZE_ENTITIES, {}) \ + .get(entity_id, {}) \ + .get(media_content_type, default_stream_query) + + return default_stream_query From 42699b7a60779ba9d56b4b8a600595b6c759fea7 Mon Sep 17 00:00:00 2001 From: Jeff Wilson Date: Wed, 19 Jul 2017 06:20:45 -0400 Subject: [PATCH 038/118] Report Harmony remote off if state is unknown (#8547) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an optional extended description… --- homeassistant/components/remote/harmony.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/remote/harmony.py b/homeassistant/components/remote/harmony.py index 165bd0b9114..cdc6a7ac61f 100755 --- a/homeassistant/components/remote/harmony.py +++ b/homeassistant/components/remote/harmony.py @@ -174,7 +174,7 @@ class HarmonyRemote(remote.RemoteDevice): @property def is_on(self): """Return False if PowerOff is the current activity, otherwise True.""" - return self._current_activity != 'PowerOff' + return self._current_activity not in [None, 'PowerOff'] def update(self): """Return current activity.""" From c8bfcd2ed4c94e863332eb308ad63d406017eb19 Mon Sep 17 00:00:00 2001 From: viswa-swami Date: Wed, 19 Jul 2017 06:21:39 -0400 Subject: [PATCH 039/118] Upgrade the alarmdecoder dependency library from 0.12.1 to 0.12.3. (#8542) * Upgrade the alarmdecoder dependency library from 0.12.1 to 0.12.3. Nutech software who owns this library have upgraded this library with some fixes regarding arming it to home/away and then disarming the alarm. Without this upgraded library, HASS is having a problem when we try to disarm an armed alarm after around 8 hours or so. * Updated the requirements_all.txt by running the script gen_requirements_all.py --- homeassistant/components/alarmdecoder.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/alarmdecoder.py b/homeassistant/components/alarmdecoder.py index d4948429b81..011cc3ad21d 100644 --- a/homeassistant/components/alarmdecoder.py +++ b/homeassistant/components/alarmdecoder.py @@ -15,7 +15,7 @@ from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.helpers.discovery import async_load_platform from homeassistant.helpers.dispatcher import async_dispatcher_send -REQUIREMENTS = ['alarmdecoder==0.12.1.0'] +REQUIREMENTS = ['alarmdecoder==0.12.3'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index c11959387b1..a6e559377e9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -58,7 +58,7 @@ aiolifx_effects==0.1.1 aiopvapi==1.4 # homeassistant.components.alarmdecoder -alarmdecoder==0.12.1.0 +alarmdecoder==0.12.3 # homeassistant.components.amcrest amcrest==1.2.0 From c27074e6f7b1a4eab75e15c055b29b4d4f1125a0 Mon Sep 17 00:00:00 2001 From: Eugenio Panadero Date: Wed, 19 Jul 2017 19:33:16 +0200 Subject: [PATCH 040/118] turn_on_action and turn_off_action with script syntax (#8558) --- homeassistant/components/media_player/kodi.py | 94 +++++++++++++++---- 1 file changed, 76 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/media_player/kodi.py b/homeassistant/components/media_player/kodi.py index f484c04a058..3764677c847 100644 --- a/homeassistant/components/media_player/kodi.py +++ b/homeassistant/components/media_player/kodi.py @@ -5,6 +5,7 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/media_player.kodi/ """ import asyncio +from collections import OrderedDict from functools import wraps import logging import urllib @@ -20,15 +21,18 @@ from homeassistant.components.media_player import ( SUPPORT_PLAY_MEDIA, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, SUPPORT_STOP, SUPPORT_TURN_OFF, SUPPORT_PLAY, SUPPORT_VOLUME_STEP, SUPPORT_SHUFFLE_SET, MediaPlayerDevice, PLATFORM_SCHEMA, MEDIA_TYPE_MUSIC, MEDIA_TYPE_TVSHOW, - MEDIA_TYPE_VIDEO, MEDIA_TYPE_PLAYLIST, MEDIA_PLAYER_SCHEMA, DOMAIN) + MEDIA_TYPE_VIDEO, MEDIA_TYPE_PLAYLIST, MEDIA_PLAYER_SCHEMA, DOMAIN, + SUPPORT_TURN_ON) from homeassistant.const import ( STATE_IDLE, STATE_OFF, STATE_PAUSED, STATE_PLAYING, CONF_HOST, CONF_NAME, CONF_PORT, CONF_SSL, CONF_PROXY_SSL, CONF_USERNAME, CONF_PASSWORD, CONF_TIMEOUT, EVENT_HOMEASSISTANT_STOP) from homeassistant.core import callback from homeassistant.helpers.aiohttp_client import async_get_clientsession -import homeassistant.helpers.config_validation as cv +from homeassistant.helpers import script, config_validation as cv from homeassistant.helpers.deprecation import get_deprecated +from homeassistant.helpers.template import Template +from homeassistant.util.yaml import dump REQUIREMENTS = ['jsonrpc-async==0.6', 'jsonrpc-websocket==0.5'] @@ -37,6 +41,7 @@ _LOGGER = logging.getLogger(__name__) EVENT_KODI_CALL_METHOD_RESULT = 'kodi_call_method_result' CONF_TCP_PORT = 'tcp_port' +CONF_TURN_ON_ACTION = 'turn_on_action' CONF_TURN_OFF_ACTION = 'turn_off_action' CONF_ENABLE_WEBSOCKET = 'enable_websocket' @@ -47,7 +52,14 @@ DEFAULT_TIMEOUT = 5 DEFAULT_PROXY_SSL = False DEFAULT_ENABLE_WEBSOCKET = True -TURN_OFF_ACTION = [None, 'quit', 'hibernate', 'suspend', 'reboot', 'shutdown'] +DEPRECATED_TURN_OFF_ACTIONS = { + None: None, + 'quit': 'Application.Quit', + 'hibernate': 'System.Hibernate', + 'suspend': 'System.Suspend', + 'reboot': 'System.Reboot', + 'shutdown': 'System.Shutdown' +} # https://github.com/xbmc/xbmc/blob/master/xbmc/media/MediaType.h MEDIA_TYPES = { @@ -75,7 +87,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_TCP_PORT, default=DEFAULT_TCP_PORT): cv.port, vol.Optional(CONF_PROXY_SSL, default=DEFAULT_PROXY_SSL): cv.boolean, - vol.Optional(CONF_TURN_OFF_ACTION, default=None): vol.In(TURN_OFF_ACTION), + vol.Optional(CONF_TURN_ON_ACTION, default=None): cv.SCRIPT_SCHEMA, + vol.Optional(CONF_TURN_OFF_ACTION): + vol.Any(cv.SCRIPT_SCHEMA, vol.In(DEPRECATED_TURN_OFF_ACTIONS)), vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, vol.Inclusive(CONF_USERNAME, 'auth'): cv.string, vol.Inclusive(CONF_PASSWORD, 'auth'): cv.string, @@ -114,11 +128,36 @@ SERVICE_TO_METHOD = { } +def _check_deprecated_turn_off(hass, turn_off_action): + """Create an equivalent script for old turn off actions.""" + if isinstance(turn_off_action, str): + method = DEPRECATED_TURN_OFF_ACTIONS[turn_off_action] + new_config = OrderedDict( + [('service', '{}.{}'.format(DOMAIN, SERVICE_CALL_METHOD)), + ('data_template', OrderedDict( + [('entity_id', '{{ entity_id }}'), + ('method', method)]))]) + example_conf = dump(OrderedDict( + [(CONF_TURN_OFF_ACTION, new_config)])) + _LOGGER.warning( + "The '%s' action for turn off Kodi is deprecated and " + "will cease to function in a future release. You need to " + "change it for a generic Home Assistant script sequence, " + "which is, for this turn_off action, like this:\n%s", + turn_off_action, example_conf) + new_config['data_template'] = OrderedDict( + [(key, Template(value, hass)) + for key, value in new_config['data_template'].items()]) + turn_off_action = [new_config] + return turn_off_action + + @asyncio.coroutine def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the Kodi platform.""" if DATA_KODI not in hass.data: hass.data[DATA_KODI] = [] + name = config.get(CONF_NAME) host = config.get(CONF_HOST) port = config.get(CONF_PORT) tcp_port = config.get(CONF_TCP_PORT) @@ -134,10 +173,11 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): entity = KodiDevice( hass, - name=config.get(CONF_NAME), + name=name, host=host, port=port, tcp_port=tcp_port, encryption=encryption, username=config.get(CONF_USERNAME), password=config.get(CONF_PASSWORD), + turn_on_action=config.get(CONF_TURN_ON_ACTION), turn_off_action=config.get(CONF_TURN_OFF_ACTION), timeout=config.get(CONF_TIMEOUT), websocket=websocket) @@ -210,7 +250,8 @@ class KodiDevice(MediaPlayerDevice): """Representation of a XBMC/Kodi device.""" def __init__(self, hass, name, host, port, tcp_port, encryption=False, - username=None, password=None, turn_off_action=None, + username=None, password=None, + turn_on_action=None, turn_off_action=None, timeout=DEFAULT_TIMEOUT, websocket=True): """Initialize the Kodi device.""" import jsonrpc_async @@ -262,6 +303,17 @@ class KodiDevice(MediaPlayerDevice): else: self._ws_server = None + # Script creation for the turn on/off config options + if turn_on_action is not None: + turn_on_action = script.Script( + self.hass, turn_on_action, + "{} turn ON script".format(self.name), + self.async_update_ha_state(True)) + if turn_off_action is not None: + turn_off_action = script.Script( + self.hass, _check_deprecated_turn_off(hass, turn_off_action), + "{} turn OFF script".format(self.name)) + self._turn_on_action = turn_on_action self._turn_off_action = turn_off_action self._enable_websocket = websocket self._players = list() @@ -304,7 +356,7 @@ class KodiDevice(MediaPlayerDevice): @callback def async_on_quit(self, sender, data): - """Handle the muted volume.""" + """Reset the player state on quit action.""" self._players = None self._properties = {} self._item = {} @@ -520,25 +572,31 @@ class KodiDevice(MediaPlayerDevice): """Flag media player features that are supported.""" supported_features = SUPPORT_KODI - if self._turn_off_action in TURN_OFF_ACTION: + if self._turn_on_action is not None: + supported_features |= SUPPORT_TURN_ON + + if self._turn_off_action is not None: supported_features |= SUPPORT_TURN_OFF return supported_features + @cmd + @asyncio.coroutine + def async_turn_on(self): + """Execute turn_on_action to turn on media player.""" + if self._turn_on_action is not None: + yield from self._turn_on_action.async_run( + variables={"entity_id": self.entity_id}) + else: + _LOGGER.warning("turn_on requested but turn_on_action is none") + @cmd @asyncio.coroutine def async_turn_off(self): """Execute turn_off_action to turn off media player.""" - if self._turn_off_action == 'quit': - yield from self.server.Application.Quit() - elif self._turn_off_action == 'hibernate': - yield from self.server.System.Hibernate() - elif self._turn_off_action == 'suspend': - yield from self.server.System.Suspend() - elif self._turn_off_action == 'reboot': - yield from self.server.System.Reboot() - elif self._turn_off_action == 'shutdown': - yield from self.server.System.Shutdown() + if self._turn_off_action is not None: + yield from self._turn_off_action.async_run( + variables={"entity_id": self.entity_id}) else: _LOGGER.warning("turn_off requested but turn_off_action is none") From f1280d3edb35b12fcfcfee433cc4149e45c1068c Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Wed, 19 Jul 2017 13:45:53 -0400 Subject: [PATCH 041/118] Extends Pi-hole sensor to support the new sensors: (#8549) - domains_being_blocked - queries_cached - queries_forwarded - unique_clients - unique_domains --- homeassistant/components/sensor/pi_hole.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/pi_hole.py b/homeassistant/components/sensor/pi_hole.py index f788fc8fd17..13421aca61d 100644 --- a/homeassistant/components/sensor/pi_hole.py +++ b/homeassistant/components/sensor/pi_hole.py @@ -36,11 +36,21 @@ SCAN_INTERVAL = timedelta(minutes=5) MONITORED_CONDITIONS = { 'dns_queries_today': ['DNS Queries Today', - None, 'mdi:network-question'], + None, 'mdi:comment-question-outline'], 'ads_blocked_today': ['Ads Blocked Today', None, 'mdi:close-octagon-outline'], 'ads_percentage_today': ['Ads Percentage Blocked Today', '%', 'mdi:close-octagon-outline'], + 'domains_being_blocked': ['Domains Blocked', + None, 'mdi:block-helper'], + 'queries_cached': ['DNS Queries Cached', + None, 'mdi:comment-question-outline'], + 'queries_forwarded': ['DNS Queries Forwarded', + None, 'mdi:comment-question-outline'], + 'unique_clients': ['DNS Unique Clients', + None, 'mdi:account-outline'], + 'unique_domains': ['DNS Unique Domains', + None, 'mdi:domain'], } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ From 84ebcd8a592d4661e1bf44619104512c7cd7c15c Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Wed, 19 Jul 2017 18:27:39 -0400 Subject: [PATCH 042/118] Support for Wink Switch and Light groups also fix fan speed selection (#8501) * Support for Switch and Light groups, fix fan speed * Fixed hound violations --- homeassistant/components/fan/wink.py | 14 +++++++++++--- homeassistant/components/light/wink.py | 6 +++++- homeassistant/components/switch/wink.py | 4 ++++ homeassistant/components/wink.py | 5 +++-- requirements_all.txt | 2 +- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/fan/wink.py b/homeassistant/components/fan/wink.py index c649009b230..3920e606d90 100644 --- a/homeassistant/components/fan/wink.py +++ b/homeassistant/components/fan/wink.py @@ -9,7 +9,8 @@ import logging from homeassistant.components.fan import (FanEntity, SPEED_HIGH, SPEED_LOW, SPEED_MEDIUM, - STATE_UNKNOWN) + STATE_UNKNOWN, SUPPORT_SET_SPEED, + SUPPORT_DIRECTION) from homeassistant.helpers.entity import ToggleEntity from homeassistant.components.wink import WinkDevice, DOMAIN @@ -20,6 +21,8 @@ _LOGGER = logging.getLogger(__name__) SPEED_LOWEST = 'lowest' SPEED_AUTO = 'auto' +SUPPORTED_FEATURES = SUPPORT_DIRECTION + SUPPORT_SET_SPEED + def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Wink platform.""" @@ -44,11 +47,11 @@ class WinkFanDevice(WinkDevice, FanEntity): def set_speed(self: ToggleEntity, speed: str) -> None: """Set the speed of the fan.""" - self.wink.set_fan_speed(speed) + self.wink.set_state(True, speed) def turn_on(self: ToggleEntity, speed: str=None, **kwargs) -> None: """Turn on the fan.""" - self.wink.set_state(True) + self.wink.set_state(True, speed) def turn_off(self: ToggleEntity, **kwargs) -> None: """Turn off the fan.""" @@ -96,3 +99,8 @@ class WinkFanDevice(WinkDevice, FanEntity): if SPEED_HIGH in wink_supported_speeds: supported_speeds.append(SPEED_HIGH) return supported_speeds + + @property + def supported_features(self: ToggleEntity) -> int: + """Flag supported features.""" + return SUPPORTED_FEATURES diff --git a/homeassistant/components/light/wink.py b/homeassistant/components/light/wink.py index 93b23a9d7ba..445fe8ceb25 100644 --- a/homeassistant/components/light/wink.py +++ b/homeassistant/components/light/wink.py @@ -28,6 +28,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _id = light.object_id() + light.name() if _id not in hass.data[DOMAIN]['unique_ids']: add_devices([WinkLight(light, hass)]) + for light in pywink.get_light_groups(): + _id = light.object_id() + light.name() + if _id not in hass.data[DOMAIN]['unique_ids']: + add_devices([WinkLight(light, hass)]) class WinkLight(WinkDevice, Light): @@ -101,7 +105,7 @@ class WinkLight(WinkDevice, Light): xyb = color_util.color_RGB_to_xy(*rgb_color) state_kwargs['color_xy'] = xyb[0], xyb[1] state_kwargs['brightness'] = xyb[2] - elif self.wink.supports_hue_saturation(): + if self.wink.supports_hue_saturation(): hsv = colorsys.rgb_to_hsv( rgb_color[0], rgb_color[1], rgb_color[2]) state_kwargs['color_hue_saturation'] = hsv[0], hsv[1] diff --git a/homeassistant/components/switch/wink.py b/homeassistant/components/switch/wink.py index 0076355665c..ec9311ac9e9 100644 --- a/homeassistant/components/switch/wink.py +++ b/homeassistant/components/switch/wink.py @@ -32,6 +32,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _id = sprinkler.object_id() + sprinkler.name() if _id not in hass.data[DOMAIN]['unique_ids']: add_devices([WinkToggleDevice(sprinkler, hass)]) + for switch in pywink.get_binary_switch_groups(): + _id = switch.object_id() + switch.name() + if _id not in hass.data[DOMAIN]['unique_ids']: + add_devices([WinkToggleDevice(switch, hass)]) class WinkToggleDevice(WinkDevice, ToggleEntity): diff --git a/homeassistant/components/wink.py b/homeassistant/components/wink.py index 1c0410a4aa0..7024291e7fe 100644 --- a/homeassistant/components/wink.py +++ b/homeassistant/components/wink.py @@ -19,7 +19,7 @@ from homeassistant.const import ( from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['python-wink==1.2.4', 'pubnubsub-handler==1.0.2'] +REQUIREMENTS = ['python-wink==1.3.1', 'pubnubsub-handler==1.0.2'] _LOGGER = logging.getLogger(__name__) @@ -105,7 +105,8 @@ def setup(hass, config): password = config[DOMAIN][CONF_PASSWORD] client_id = config[DOMAIN]['client_id'] client_secret = config[DOMAIN]['client_secret'] - pywink.set_wink_credentials(email, password, client_id, client_secret) + pywink.legacy_set_wink_credentials(email, password, + client_id, client_secret) hass.data[DOMAIN]['oath'] = {"email": email, "password": password, "client_id": client_id, diff --git a/requirements_all.txt b/requirements_all.txt index a6e559377e9..aee9aec89fa 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -755,7 +755,7 @@ python-twitch==1.3.0 python-vlc==1.1.2 # homeassistant.components.wink -python-wink==1.2.4 +python-wink==1.3.1 # homeassistant.components.zwave python_openzwave==0.4.0.31 From 54755df9eac7409c191cdafb874235ca4a4d6e16 Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Thu, 20 Jul 2017 07:01:05 +0200 Subject: [PATCH 043/118] Added a service to write to KNX group addressed including documentation (#8491) * Added a service to write to KNX group addressed including documentation * Define parameters as required * Reformating * Moved service documentation to service.yaml * Moved service documentation to services.yaml * Update knx.py --- homeassistant/components/knx.py | 71 ++++++++++++++------------ homeassistant/components/services.yaml | 13 +++++ 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/homeassistant/components/knx.py b/homeassistant/components/knx.py index 9772c19ff78..9530becb6ce 100644 --- a/homeassistant/components/knx.py +++ b/homeassistant/components/knx.py @@ -5,6 +5,7 @@ For more details about this component, please refer to the documentation at https://home-assistant.io/components/knx/ """ import logging +import os import voluptuous as vol @@ -12,6 +13,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP, CONF_HOST, CONF_PORT) from homeassistant.helpers.entity import Entity +from homeassistant.config import load_yaml_config_file REQUIREMENTS = ['knxip==0.5'] @@ -25,6 +27,9 @@ EVENT_KNX_FRAME_RECEIVED = 'knx_frame_received' EVENT_KNX_FRAME_SEND = 'knx_frame_send' KNXTUNNEL = None +KNX_ADDRESS = "address" +KNX_DATA = "data" +KNX_GROUP_WRITE = "group_write" CONF_LISTEN = "listen" CONFIG_SCHEMA = vol.Schema({ @@ -36,6 +41,11 @@ CONFIG_SCHEMA = vol.Schema({ }), }, extra=vol.ALLOW_EXTRA) +KNX_WRITE_SCHEMA = vol.Schema({ + vol.Required(KNX_ADDRESS): vol.All(cv.ensure_list, [cv.string]), + vol.Required(KNX_DATA): vol.All(cv.ensure_list, [cv.byte]) +}) + def setup(hass, config): """Set up the connection to the KNX IP interface.""" @@ -65,6 +75,9 @@ def setup(hass, config): _LOGGER.info("KNX IP tunnel to %s:%i established", host, port) + descriptions = load_yaml_config_file( + os.path.join(os.path.dirname(__file__), 'services.yaml')) + def received_knx_event(address, data): """Process received KNX message.""" if len(data) == 1: @@ -86,47 +99,37 @@ def setup(hass, config): hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, close_tunnel) # Listen to KNX events and send them to the bus - def handle_knx_send(event): + def handle_group_write(call): """Bridge knx_frame_send events to the KNX bus.""" - try: - addr = event.data["address"] - except KeyError: - _LOGGER.error("KNX group address is missing") - return + # parameters are pre-validated using KNX_WRITE_SCHEMA + addrlist = call.data.get("address") + knxdata = call.data.get("data") - try: - data = event.data["data"] - except KeyError: - _LOGGER.error("KNX data block missing") - return - - knxaddr = None - try: - addr = int(addr) - except ValueError: - pass - - if knxaddr is None: + knxaddrlist = [] + for addr in addrlist: try: - knxaddr = parse_group_address(addr) - except KNXException: - _LOGGER.error("KNX address format incorrect") - return - - knxdata = None - if isinstance(data, list): - knxdata = data - else: - try: - knxdata = [int(data) & 0xff] + _LOGGER.debug("Found %s", addr) + knxaddr = int(addr) except ValueError: - _LOGGER.error("KNX data format incorrect") - return + knxaddr = None - KNXTUNNEL.group_write(knxaddr, knxdata) + if knxaddr is None: + try: + knxaddr = parse_group_address(addr) + except KNXException: + _LOGGER.error("KNX address format incorrect: %s", addr) + + knxaddrlist.append(knxaddr) + + for addr in knxaddrlist: + KNXTUNNEL.group_write(addr, knxdata) # Listen for when knx_frame_send event is fired - hass.bus.listen(EVENT_KNX_FRAME_SEND, handle_knx_send) + hass.services.register(DOMAIN, + KNX_GROUP_WRITE, + handle_group_write, + descriptions[DOMAIN][KNX_GROUP_WRITE], + schema=KNX_WRITE_SCHEMA) return True diff --git a/homeassistant/components/services.yaml b/homeassistant/components/services.yaml index eefcff5bd17..880a539927a 100644 --- a/homeassistant/components/services.yaml +++ b/homeassistant/components/services.yaml @@ -520,3 +520,16 @@ wake_on_lan: broadcast_address: description: Optional broadcast IP where to send the magic packet. example: '192.168.255.255' + +knx: + group_write: + description: Turn a light on + + fields: + address: + description: Group address(es) to write to + example: '1/1/0' + + data: + description: KNX data to send + example: 1 From 9cc3e7e47b3cbfa18783e2842f924624c10ef850 Mon Sep 17 00:00:00 2001 From: Jeff Wilson Date: Thu, 20 Jul 2017 01:51:50 -0400 Subject: [PATCH 044/118] Handle manual edits to emulated_hue_ids.json (#8560) --- homeassistant/components/emulated_hue/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/emulated_hue/__init__.py b/homeassistant/components/emulated_hue/__init__.py index b0b6ec0324f..315fc564999 100644 --- a/homeassistant/components/emulated_hue/__init__.py +++ b/homeassistant/components/emulated_hue/__init__.py @@ -193,7 +193,7 @@ class Config(object): if entity_id == ent_id: return number - number = str(len(self.numbers) + 1) + number = str(max(int(k) for k in self.numbers) + 1) self.numbers[number] = entity_id self._save_numbers_json() return number From 8a42e1551a54fd6c1e1e383dd63a050d09e889ef Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Thu, 20 Jul 2017 07:54:46 +0200 Subject: [PATCH 045/118] LIFX: assume default features for unknown products (#8553) This makes the detection work for prototypes as well. --- homeassistant/components/light/lifx.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/light/lifx.py b/homeassistant/components/light/lifx.py index a32aa0c4a6b..a6c5f855875 100644 --- a/homeassistant/components/light/lifx.py +++ b/homeassistant/components/light/lifx.py @@ -159,12 +159,18 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def lifxwhite(device): """Return whether this is a white-only bulb.""" - return not aiolifx().products.features_map[device.product]["color"] + features = aiolifx().products.features_map.get(device.product, None) + if features: + return not features["color"] + return False def lifxmultizone(device): """Return whether this is a multizone bulb/strip.""" - return aiolifx().products.features_map[device.product]["multizone"] + features = aiolifx().products.features_map.get(device.product, None) + if features: + return features["multizone"] + return False def find_hsbk(**kwargs): From ee05a4ab892ac6faf396fe90a9ae61f0cba318e8 Mon Sep 17 00:00:00 2001 From: Yannick POLLART Date: Thu, 20 Jul 2017 07:56:11 +0200 Subject: [PATCH 046/118] Fix broken status update for lighting4 devices (#8543) * Fix broken status update for lighting4 devices * Fixed indentation --- .../components/binary_sensor/rfxtrx.py | 20 +++++++++---------- homeassistant/components/rfxtrx.py | 11 ++-------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/binary_sensor/rfxtrx.py b/homeassistant/components/binary_sensor/rfxtrx.py index 9a2c23206c1..b70169dc594 100644 --- a/homeassistant/components/binary_sensor/rfxtrx.py +++ b/homeassistant/components/binary_sensor/rfxtrx.py @@ -62,6 +62,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): entity[CONF_COMMAND_ON], entity[CONF_COMMAND_OFF]) device.hass = hass + device.is_lighting4 = (packet_id[2:4] == '13') sensors.append(device) rfxtrx.RFX_DEVICES[device_id] = device @@ -94,6 +95,8 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): pkt_id = "".join("{0:02x}".format(x) for x in event.data) sensor = RfxtrxBinarySensor(event, pkt_id) + sensor.hass = hass + sensor.is_lighting4 = (pkt_id[2:4] == '13') rfxtrx.RFX_DEVICES[device_id] = sensor add_devices_callback([sensor]) _LOGGER.info("Added binary sensor %s " @@ -111,12 +114,12 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): slugify(event.device.id_string.lower()), event.device.__class__.__name__, event.device.subtype) - - if sensor.is_pt2262: - cmd = rfxtrx.get_pt2262_cmd(device_id, sensor.data_bits) - _LOGGER.info("applying cmd %s to device_id: %s)", - cmd, sensor.masked_id) - sensor.apply_cmd(int(cmd, 16)) + if sensor.is_lighting4: + if sensor.data_bits is not None: + cmd = rfxtrx.get_pt2262_cmd(device_id, sensor.data_bits) + sensor.apply_cmd(int(cmd, 16)) + else: + sensor.update_state(True) else: rfxtrx.apply_received_command(event) @@ -170,11 +173,6 @@ class RfxtrxBinarySensor(BinarySensorDevice): """Return the device name.""" return self._name - @property - def is_pt2262(self): - """Return true if the device is PT2262-based.""" - return self._data_bits is not None - @property def masked_id(self): """Return the masked device id (isolated address bits).""" diff --git a/homeassistant/components/rfxtrx.py b/homeassistant/components/rfxtrx.py index b6e4d3415f4..e3ffc2f24a8 100644 --- a/homeassistant/components/rfxtrx.py +++ b/homeassistant/components/rfxtrx.py @@ -247,10 +247,8 @@ def get_pt2262_device(device_id): """Look for the device which id matches the given device_id parameter.""" for dev_id, device in RFX_DEVICES.items(): try: - if (device.is_pt2262 and - device.masked_id == get_pt2262_deviceid( - device_id, - device.data_bits)): + if device.masked_id == get_pt2262_deviceid(device_id, + device.data_bits): _LOGGER.info("rfxtrx: found matching device %s for %s", device_id, get_pt2262_deviceid(device_id, device.data_bits)) @@ -414,11 +412,6 @@ class RfxtrxDevice(Entity): """Return is the device must fire event.""" return self._should_fire_event - @property - def is_pt2262(self): - """Return true if the device is PT2262-based.""" - return False - @property def is_on(self): """Return true if device is on.""" From 8d1999dc1205fb8c2156b0a3ed66f1320574b7ed Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Thu, 20 Jul 2017 01:56:24 -0400 Subject: [PATCH 047/118] Enhance python_script to support "_getitem_" (#8541) * Enhance python_script to support "_getitem_" In order to use dict / list structures in python scripts we need _getitem_ allowed in the RestrictedPython environment. There is a default_guarded_getitem included with RestrictedPython, which is a pass through used in the Eval code paths. * Add tests for dict/list support in python_scripts * Lint --- homeassistant/components/python_script.py | 2 ++ tests/components/test_python_script.py | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/homeassistant/components/python_script.py b/homeassistant/components/python_script.py index 66b9bd0112a..386abba59ae 100644 --- a/homeassistant/components/python_script.py +++ b/homeassistant/components/python_script.py @@ -65,6 +65,7 @@ def execute(hass, filename, source, data=None): from RestrictedPython import compile_restricted_exec from RestrictedPython.Guards import safe_builtins, full_write_guard from RestrictedPython.Utilities import utility_builtins + from RestrictedPython.Eval import default_guarded_getitem compiled = compile_restricted_exec(source, filename=filename) @@ -99,6 +100,7 @@ def execute(hass, filename, source, data=None): '_getattr_': protected_getattr, '_write_': full_write_guard, '_getiter_': iter, + '_getitem_': default_guarded_getitem } logger = logging.getLogger('{}.{}'.format(__name__, filename)) local = { diff --git a/tests/components/test_python_script.py b/tests/components/test_python_script.py index 78142e06cf3..62c1b67eba9 100644 --- a/tests/components/test_python_script.py +++ b/tests/components/test_python_script.py @@ -137,6 +137,22 @@ hass.async_stop() assert "Not allowed to access async methods" in caplog.text +@asyncio.coroutine +def test_using_complex_structures(hass, caplog): + """Test that dicts and lists work.""" + caplog.set_level(logging.INFO) + source = """ +mydict = {"a": 1, "b": 2} +mylist = [1, 2, 3, 4] +logger.info('Logging from inside script: %s %s' % (mydict["a"], mylist[2])) + """ + + hass.async_add_job(execute, hass, 'test.py', source, {}) + yield from hass.async_block_till_done() + + assert "Logging from inside script: 1 3" in caplog.text + + @asyncio.coroutine def test_accessing_forbidden_methods(hass, caplog): """Test compile error logs error.""" From 49c399c358bbe45b034f6e013233dc906d47ef0a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 19 Jul 2017 22:59:21 -0700 Subject: [PATCH 048/118] Update persistent deps dir version in config.py (#8479) * Update persistent deps dir version in config.py * Update last version to remove deps dir in tests --- homeassistant/config.py | 4 ++-- tests/test_config.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/config.py b/homeassistant/config.py index 003e6481685..a4b7bce5dc0 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -297,8 +297,8 @@ def process_ha_config_upgrade(hass): _LOGGER.info("Upgrading configuration directory from %s to %s", conf_version, __version__) - if LooseVersion(conf_version) < LooseVersion('0.49'): - # 0.49 introduced persistent deps dir. + if LooseVersion(conf_version) < LooseVersion('0.50'): + # 0.50 introduced persistent deps dir. lib_path = hass.config.path('deps') if os.path.isdir(lib_path): shutil.rmtree(lib_path) diff --git a/tests/test_config.py b/tests/test_config.py index eba98795fe9..8c889979a82 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -260,8 +260,8 @@ class TestConfig(unittest.TestCase): @mock.patch('homeassistant.config.shutil') @mock.patch('homeassistant.config.os') def test_remove_lib_on_upgrade(self, mock_os, mock_shutil): - """Test removal of library on upgrade from before 0.49.""" - ha_version = '0.48.0' + """Test removal of library on upgrade from before 0.50.""" + ha_version = '0.49.0' mock_os.path.isdir = mock.Mock(return_value=True) mock_open = mock.mock_open() with mock.patch('homeassistant.config.open', mock_open, create=True): From fde291f8666594e61d7fd02b5bdfc648042e9af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Thu, 20 Jul 2017 11:12:42 +0200 Subject: [PATCH 049/118] Add is_lighting4 to RfxtrxBinarySensor (#8563) --- homeassistant/components/binary_sensor/rfxtrx.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/binary_sensor/rfxtrx.py b/homeassistant/components/binary_sensor/rfxtrx.py index b70169dc594..e86c948e191 100644 --- a/homeassistant/components/binary_sensor/rfxtrx.py +++ b/homeassistant/components/binary_sensor/rfxtrx.py @@ -154,6 +154,7 @@ class RfxtrxBinarySensor(BinarySensorDevice): self._device_class = device_class self._off_delay = off_delay self._state = False + self.is_lighting4 = False self.delay_listener = None self._data_bits = data_bits self._cmd_on = cmd_on From bc27d173d010179b34be8b2f23c746ab2fbbedd5 Mon Sep 17 00:00:00 2001 From: pavoni Date: Thu, 20 Jul 2017 10:21:08 +0100 Subject: [PATCH 050/118] Bump pyver to fix exception in fetching colours. --- homeassistant/components/vera.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/vera.py b/homeassistant/components/vera.py index b43cea3fcea..2183e20188f 100644 --- a/homeassistant/components/vera.py +++ b/homeassistant/components/vera.py @@ -20,7 +20,7 @@ from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP) from homeassistant.helpers.entity import Entity -REQUIREMENTS = ['pyvera==0.2.34'] +REQUIREMENTS = ['pyvera==0.2.35'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index aee9aec89fa..1adc4778eba 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -773,7 +773,7 @@ pyunifi==2.13 # pyuserinput==0.1.11 # homeassistant.components.vera -pyvera==0.2.34 +pyvera==0.2.35 # homeassistant.components.media_player.vizio pyvizio==0.0.2 From 90639d33ab6b574abfec71b8ebbdd86cefff9081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Thu, 20 Jul 2017 15:20:00 +0200 Subject: [PATCH 051/118] Xiaomi gw support (#8555) * xiaomi support * xiaomi support * style * style * style * style * style * coveragerc * Update xiaomi.py * Update xiaomi.py * Update xiaomi.py * refactorization * refactorization * config validation * style * package * refactorization * refactorization * refactorization * HA integration --- .coveragerc | 4 +- .../components/binary_sensor/xiaomi.py | 316 ++++++++++++++++++ homeassistant/components/cover/xiaomi.py | 66 ++++ homeassistant/components/light/xiaomi.py | 103 ++++++ homeassistant/components/sensor/xiaomi.py | 77 +++++ homeassistant/components/switch/xiaomi.py | 111 ++++++ homeassistant/components/xiaomi.py | 195 +++++++++++ requirements_all.txt | 3 + 8 files changed, 874 insertions(+), 1 deletion(-) create mode 100644 homeassistant/components/binary_sensor/xiaomi.py create mode 100644 homeassistant/components/cover/xiaomi.py create mode 100755 homeassistant/components/light/xiaomi.py create mode 100644 homeassistant/components/sensor/xiaomi.py create mode 100644 homeassistant/components/switch/xiaomi.py create mode 100644 homeassistant/components/xiaomi.py diff --git a/.coveragerc b/.coveragerc index 2d1bff462b9..3ec0b119cb8 100644 --- a/.coveragerc +++ b/.coveragerc @@ -193,6 +193,9 @@ omit = homeassistant/components/wink.py homeassistant/components/*/wink.py + homeassistant/components/xiaomi.py + homeassistant/components/*/xiaomi.py + homeassistant/components/zabbix.py homeassistant/components/*/zabbix.py @@ -274,7 +277,6 @@ omit = homeassistant/components/device_tracker/tplink.py homeassistant/components/device_tracker/trackr.py homeassistant/components/device_tracker/ubus.py - homeassistant/components/device_tracker/xiaomi.py homeassistant/components/downloader.py homeassistant/components/emoncms_history.py homeassistant/components/emulated_hue/upnp.py diff --git a/homeassistant/components/binary_sensor/xiaomi.py b/homeassistant/components/binary_sensor/xiaomi.py new file mode 100644 index 00000000000..14d2ef9b308 --- /dev/null +++ b/homeassistant/components/binary_sensor/xiaomi.py @@ -0,0 +1,316 @@ +"""Support for Xiaomi binary sensors.""" +import logging + +from homeassistant.components.binary_sensor import BinarySensorDevice +from homeassistant.components.xiaomi import (PY_XIAOMI_GATEWAY, XiaomiDevice) + +_LOGGER = logging.getLogger(__name__) + +NO_CLOSE = 'no_close' +ATTR_OPEN_SINCE = 'Open since' + +MOTION = 'motion' +NO_MOTION = 'no_motion' +ATTR_NO_MOTION_SINCE = 'No motion since' + +DENSITY = 'density' +ATTR_DENSITY = 'Density' + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Perform the setup for Xiaomi devices.""" + devices = [] + for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): + for device in gateway.devices['binary_sensor']: + model = device['model'] + if model == 'motion': + devices.append(XiaomiMotionSensor(device, hass, gateway)) + elif model == 'magnet': + devices.append(XiaomiDoorSensor(device, gateway)) + elif model == 'smoke': + devices.append(XiaomiSmokeSensor(device, gateway)) + elif model == 'natgas': + devices.append(XiaomiNatgasSensor(device, gateway)) + elif model == 'switch': + devices.append(XiaomiButton(device, 'Switch', 'status', + hass, gateway)) + elif model == 'sensor_switch.aq2': + devices.append(XiaomiButton(device, 'Switch', 'status', + hass, gateway)) + elif model == '86sw1': + devices.append(XiaomiButton(device, 'Wall Switch', 'channel_0', + hass, gateway)) + elif model == '86sw2': + devices.append(XiaomiButton(device, 'Wall Switch (Left)', + 'channel_0', hass, gateway)) + devices.append(XiaomiButton(device, 'Wall Switch (Right)', + 'channel_1', hass, gateway)) + devices.append(XiaomiButton(device, 'Wall Switch (Both)', + 'dual_channel', hass, gateway)) + elif model == 'cube': + devices.append(XiaomiCube(device, hass, gateway)) + add_devices(devices) + + +class XiaomiBinarySensor(XiaomiDevice, BinarySensorDevice): + """Representation of a base XiaomiBinarySensor.""" + + def __init__(self, device, name, xiaomi_hub): + """Initialize the XiaomiSmokeSensor.""" + self._data_key = None + self._device_class = None + self._should_poll = False + self._density = 0 + XiaomiDevice.__init__(self, device, name, xiaomi_hub) + + @property + def should_poll(self): + """Return True if entity has to be polled for state.""" + return self._should_poll + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def device_class(self): + """Return the class of binary sensor.""" + return self._device_class + + def update(self): + """Update the sensor state.""" + _LOGGER.debug('Updating xiaomi sensor by polling') + self._get_from_hub(self._sid) + + +class XiaomiNatgasSensor(XiaomiBinarySensor): + """Representation of a XiaomiNatgasSensor.""" + + def __init__(self, device, xiaomi_hub): + """Initialize the XiaomiSmokeSensor.""" + self._data_key = 'alarm' + self._density = None + self._device_class = 'gas' + XiaomiBinarySensor.__init__(self, device, 'Natgas Sensor', xiaomi_hub) + + @property + def device_state_attributes(self): + """Return the state attributes.""" + attrs = {ATTR_DENSITY: self._density} + attrs.update(super().device_state_attributes) + return attrs + + def parse_data(self, data): + """Parse data sent by gateway.""" + if DENSITY in data: + self._density = int(data.get(DENSITY)) + + value = data.get(self._data_key) + if value is None: + return False + + if value == '1': + if self._state: + return False + self._state = True + return True + elif value == '0': + if self._state: + self._state = False + return True + return False + + +class XiaomiMotionSensor(XiaomiBinarySensor): + """Representation of a XiaomiMotionSensor.""" + + def __init__(self, device, hass, xiaomi_hub): + """Initialize the XiaomiMotionSensor.""" + self._hass = hass + self._data_key = 'status' + self._no_motion_since = 0 + self._device_class = 'motion' + XiaomiBinarySensor.__init__(self, device, 'Motion Sensor', xiaomi_hub) + + @property + def device_state_attributes(self): + """Return the state attributes.""" + attrs = {ATTR_NO_MOTION_SINCE: self._no_motion_since} + attrs.update(super().device_state_attributes) + return attrs + + def parse_data(self, data): + """Parse data sent by gateway.""" + self._should_poll = False + if NO_MOTION in data: # handle push from the hub + self._no_motion_since = data[NO_MOTION] + self._state = False + return True + + value = data.get(self._data_key) + if value is None: + return False + + if value == MOTION: + self._should_poll = True + if self.entity_id is not None: + self._hass.bus.fire('motion', { + 'entity_id': self.entity_id + }) + + self._no_motion_since = 0 + if self._state: + return False + self._state = True + return True + elif value == NO_MOTION: + if not self._state: + return False + self._state = False + return True + + +class XiaomiDoorSensor(XiaomiBinarySensor): + """Representation of a XiaomiDoorSensor.""" + + def __init__(self, device, xiaomi_hub): + """Initialize the XiaomiDoorSensor.""" + self._data_key = 'status' + self._open_since = 0 + self._device_class = 'opening' + XiaomiBinarySensor.__init__(self, device, 'Door Window Sensor', + xiaomi_hub) + + @property + def device_state_attributes(self): + """Return the state attributes.""" + attrs = {ATTR_OPEN_SINCE: self._open_since} + attrs.update(super().device_state_attributes) + return attrs + + def parse_data(self, data): + """Parse data sent by gateway.""" + self._should_poll = False + if NO_CLOSE in data: # handle push from the hub + self._open_since = data[NO_CLOSE] + return True + + value = data.get(self._data_key) + if value is None: + return False + + if value == 'open': + self._should_poll = True + if self._state: + return False + self._state = True + return True + elif value == 'close': + self._open_since = 0 + if self._state: + self._state = False + return True + return False + + +class XiaomiSmokeSensor(XiaomiBinarySensor): + """Representation of a XiaomiSmokeSensor.""" + + def __init__(self, device, xiaomi_hub): + """Initialize the XiaomiSmokeSensor.""" + self._data_key = 'alarm' + self._density = 0 + self._device_class = 'smoke' + XiaomiBinarySensor.__init__(self, device, 'Smoke Sensor', xiaomi_hub) + + @property + def device_state_attributes(self): + """Return the state attributes.""" + attrs = {ATTR_DENSITY: self._density} + attrs.update(super().device_state_attributes) + return attrs + + def parse_data(self, data): + """Parse data sent by gateway.""" + if DENSITY in data: + self._density = int(data.get(DENSITY)) + value = data.get(self._data_key) + if value is None: + return False + + if value == '1': + if self._state: + return False + self._state = True + return True + elif value == '0': + if self._state: + self._state = False + return True + return False + + +class XiaomiButton(XiaomiBinarySensor): + """Representation of a Xiaomi Button.""" + + def __init__(self, device, name, data_key, hass, xiaomi_hub): + """Initialize the XiaomiButton.""" + self._hass = hass + self._data_key = data_key + XiaomiBinarySensor.__init__(self, device, name, xiaomi_hub) + + def parse_data(self, data): + """Parse data sent by gateway.""" + value = data.get(self._data_key) + if value is None: + return False + + if value == 'long_click_press': + self._state = True + click_type = 'long_click_press' + elif value == 'long_click_release': + self._state = False + click_type = 'hold' + elif value == 'click': + click_type = 'single' + elif value == 'double_click': + click_type = 'double' + elif value == 'both_click': + click_type = 'both' + else: + return False + + self._hass.bus.fire('click', { + 'entity_id': self.entity_id, + 'click_type': click_type + }) + if value in ['long_click_press', 'long_click_release']: + return True + return False + + +class XiaomiCube(XiaomiBinarySensor): + """Representation of a Xiaomi Cube.""" + + def __init__(self, device, hass, xiaomi_hub): + """Initialize the Xiaomi Cube.""" + self._hass = hass + self._state = False + XiaomiBinarySensor.__init__(self, device, 'Cube', xiaomi_hub) + + def parse_data(self, data): + """Parse data sent by gateway.""" + if 'status' in data: + self._hass.bus.fire('cube_action', { + 'entity_id': self.entity_id, + 'action_type': data['status'] + }) + + if 'rotate' in data: + self._hass.bus.fire('cube_action', { + 'entity_id': self.entity_id, + 'action_type': 'rotate', + 'action_value': float(data['rotate'].replace(",", ".")) + }) + return False diff --git a/homeassistant/components/cover/xiaomi.py b/homeassistant/components/cover/xiaomi.py new file mode 100644 index 00000000000..7e3b0b7044d --- /dev/null +++ b/homeassistant/components/cover/xiaomi.py @@ -0,0 +1,66 @@ +"""Support for Xiaomi curtain.""" +import logging + +from homeassistant.components.cover import CoverDevice +from homeassistant.components.xiaomi import (PY_XIAOMI_GATEWAY, XiaomiDevice) + +_LOGGER = logging.getLogger(__name__) + +ATTR_CURTAIN_LEVEL = 'curtain_level' + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Perform the setup for Xiaomi devices.""" + devices = [] + for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): + for device in gateway.devices['cover']: + model = device['model'] + if model == 'curtain': + devices.append(XiaomiGenericCover(device, "Curtain", + {'status': 'status', + 'pos': 'curtain_level'}, + gateway)) + add_devices(devices) + + +class XiaomiGenericCover(XiaomiDevice, CoverDevice): + """Representation of a XiaomiPlug.""" + + def __init__(self, device, name, data_key, xiaomi_hub): + """Initialize the XiaomiPlug.""" + self._data_key = data_key + self._pos = 0 + XiaomiDevice.__init__(self, device, name, xiaomi_hub) + + @property + def current_cover_position(self): + """Return the current position of the cover.""" + return self._pos + + @property + def is_closed(self): + """Return if the cover is closed.""" + return self.current_cover_position < 0 + + def close_cover(self, **kwargs): + """Close the cover.""" + self._write_to_hub(self._sid, self._data_key['status'], 'close') + + def open_cover(self, **kwargs): + """Open the cover.""" + self._write_to_hub(self._sid, self._data_key['status'], 'open') + + def stop_cover(self, **kwargs): + """Stop the cover.""" + self._write_to_hub(self._sid, self._data_key['status'], 'stop') + + def set_cover_position(self, position, **kwargs): + """Move the cover to a specific position.""" + self._write_to_hub(self._sid, self._data_key['pos'], str(position)) + + def parse_data(self, data): + """Parse data sent by gateway.""" + if ATTR_CURTAIN_LEVEL in data: + self._pos = int(data[ATTR_CURTAIN_LEVEL]) + return True + return False diff --git a/homeassistant/components/light/xiaomi.py b/homeassistant/components/light/xiaomi.py new file mode 100755 index 00000000000..d8a70b726f4 --- /dev/null +++ b/homeassistant/components/light/xiaomi.py @@ -0,0 +1,103 @@ +"""Support for Xiaomi Gateway Light.""" +import logging +import struct +import binascii +from homeassistant.components.xiaomi import (PY_XIAOMI_GATEWAY, XiaomiDevice) +from homeassistant.components.light import (ATTR_BRIGHTNESS, ATTR_RGB_COLOR, + SUPPORT_BRIGHTNESS, + SUPPORT_RGB_COLOR, Light) + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Perform the setup for Xiaomi devices.""" + devices = [] + for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): + for device in gateway.devices['light']: + model = device['model'] + if model == 'gateway': + devices.append(XiaomiGatewayLight(device, 'Gateway Light', + gateway)) + add_devices(devices) + + +class XiaomiGatewayLight(XiaomiDevice, Light): + """Representation of a XiaomiGatewayLight.""" + + def __init__(self, device, name, xiaomi_hub): + """Initialize the XiaomiGatewayLight.""" + self._data_key = 'rgb' + self._rgb = (255, 255, 255) + self._brightness = 180 + + XiaomiDevice.__init__(self, device, name, xiaomi_hub) + + @property + def is_on(self): + """Return true if it is on.""" + return self._state + + def parse_data(self, data): + """Parse data sent by gateway.""" + value = data.get(self._data_key) + if value is None: + return False + + if value == 0: + if self._state: + self._state = False + return True + + rgbhexstr = "%x" % value + if len(rgbhexstr) == 7: + rgbhexstr = '0' + rgbhexstr + elif len(rgbhexstr) != 8: + _LOGGER.error('Light RGB data error.' + ' Must be 8 characters. Received: %s', rgbhexstr) + return False + + rgbhex = bytes.fromhex(rgbhexstr) + rgba = struct.unpack('BBBB', rgbhex) + brightness = rgba[0] + rgb = rgba[1:] + + self._brightness = int(255 * brightness / 100) + self._rgb = rgb + self._state = True + return True + + @property + def brightness(self): + """Return the brightness of this light between 0..255.""" + return self._brightness + + @property + def rgb_color(self): + """Return the RBG color value.""" + return self._rgb + + @property + def supported_features(self): + """Return the supported features.""" + return SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR + + def turn_on(self, **kwargs): + """Turn the light on.""" + if ATTR_RGB_COLOR in kwargs: + self._rgb = kwargs[ATTR_RGB_COLOR] + + if ATTR_BRIGHTNESS in kwargs: + self._brightness = int(100 * kwargs[ATTR_BRIGHTNESS] / 255) + + rgba = (self._brightness,) + self._rgb + rgbhex = binascii.hexlify(struct.pack('BBBB', *rgba)).decode("ASCII") + rgbhex = int(rgbhex, 16) + + if self._write_to_hub(self._sid, **{self._data_key: rgbhex}): + self._state = True + + def turn_off(self, **kwargs): + """Turn the light off.""" + if self._write_to_hub(self._sid, **{self._data_key: 0}): + self._state = False diff --git a/homeassistant/components/sensor/xiaomi.py b/homeassistant/components/sensor/xiaomi.py new file mode 100644 index 00000000000..b1fcd8beb1f --- /dev/null +++ b/homeassistant/components/sensor/xiaomi.py @@ -0,0 +1,77 @@ +"""Support for Xiaomi sensors.""" +import logging + +from homeassistant.components.xiaomi import (PY_XIAOMI_GATEWAY, XiaomiDevice) +from homeassistant.const import TEMP_CELSIUS + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Perform the setup for Xiaomi devices.""" + devices = [] + for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): + for device in gateway.devices['sensor']: + if device['model'] == 'sensor_ht': + devices.append(XiaomiSensor(device, 'Temperature', + 'temperature', gateway)) + devices.append(XiaomiSensor(device, 'Humidity', + 'humidity', gateway)) + if device['model'] == 'weather.v1': + devices.append(XiaomiSensor(device, 'Temperature', + 'temperature', gateway)) + devices.append(XiaomiSensor(device, 'Humidity', + 'humidity', gateway)) + devices.append(XiaomiSensor(device, 'Pressure', + 'pressure', gateway)) + elif device['model'] == 'gateway': + devices.append(XiaomiSensor(device, 'Illumination', + 'illumination', gateway)) + add_devices(devices) + + +class XiaomiSensor(XiaomiDevice): + """Representation of a XiaomiSensor.""" + + def __init__(self, device, name, data_key, xiaomi_hub): + """Initialize the XiaomiSensor.""" + self._data_key = data_key + XiaomiDevice.__init__(self, device, name, xiaomi_hub) + + @property + def unit_of_measurement(self): + """Return the unit of measurement of this entity, if any.""" + if self._data_key == 'temperature': + return TEMP_CELSIUS + elif self._data_key == 'humidity': + return '%' + elif self._data_key == 'illumination': + return 'lm' + elif self._data_key == 'pressure': + return 'hPa' + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + def parse_data(self, data): + """Parse data sent by gateway.""" + value = data.get(self._data_key) + if value is None: + return False + value = float(value) + if self._data_key == 'temperature' and value == 10000: + return False + elif self._data_key == 'humidity' and value == 0: + return False + elif self._data_key == 'illumination' and value == 0: + return False + elif self._data_key == 'pressure' and value == 0: + return False + if self._data_key in ['temperature', 'humidity']: + value /= 100 + elif self._data_key in ['illumination']: + value = max(value - 300, 0) + self._state = round(value, 2) + return True diff --git a/homeassistant/components/switch/xiaomi.py b/homeassistant/components/switch/xiaomi.py new file mode 100644 index 00000000000..fa472136bb5 --- /dev/null +++ b/homeassistant/components/switch/xiaomi.py @@ -0,0 +1,111 @@ +"""Support for Xiaomi binary sensors.""" +import logging + +from homeassistant.components.switch import SwitchDevice +from homeassistant.components.xiaomi import (PY_XIAOMI_GATEWAY, XiaomiDevice) + +_LOGGER = logging.getLogger(__name__) + +ATTR_LOAD_POWER = 'Load power' # Load power in watts (W) +ATTR_POWER_CONSUMED = 'Power consumed' +ATTR_IN_USE = 'In use' +LOAD_POWER = 'load_power' +POWER_CONSUMED = 'power_consumed' +IN_USE = 'inuse' + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Perform the setup for Xiaomi devices.""" + devices = [] + for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): + for device in gateway.devices['switch']: + model = device['model'] + if model == 'plug': + devices.append(XiaomiGenericSwitch(device, "Plug", 'status', + True, gateway)) + elif model == 'ctrl_neutral1': + devices.append(XiaomiGenericSwitch(device, 'Wall Switch', + 'channel_0', + False, gateway)) + elif model == 'ctrl_neutral2': + devices.append(XiaomiGenericSwitch(device, 'Wall Switch Left', + 'channel_0', + False, gateway)) + devices.append(XiaomiGenericSwitch(device, 'Wall Switch Right', + 'channel_1', + False, gateway)) + elif model == '86plug': + devices.append(XiaomiGenericSwitch(device, 'Wall Plug', + 'status', True, gateway)) + add_devices(devices) + + +class XiaomiGenericSwitch(XiaomiDevice, SwitchDevice): + """Representation of a XiaomiPlug.""" + + def __init__(self, device, name, data_key, supports_power_consumption, + xiaomi_hub): + """Initialize the XiaomiPlug.""" + self._data_key = data_key + self._in_use = None + self._load_power = None + self._power_consumed = None + self._supports_power_consumption = supports_power_consumption + XiaomiDevice.__init__(self, device, name, xiaomi_hub) + + @property + def icon(self): + """Return the icon to use in the frontend, if any.""" + if self._data_key == 'status': + return 'mdi:power-plug' + return 'mdi:power-socket' + + @property + def is_on(self): + """Return true if it is on.""" + return self._state + + @property + def device_state_attributes(self): + """Return the state attributes.""" + if self._supports_power_consumption: + attrs = {ATTR_IN_USE: self._in_use, + ATTR_LOAD_POWER: self._load_power, + ATTR_POWER_CONSUMED: self._power_consumed} + else: + attrs = {} + attrs.update(super().device_state_attributes) + return attrs + + def turn_on(self, **kwargs): + """Turn the switch on.""" + if self._write_to_hub(self._sid, **{self._data_key: 'on'}): + self._state = True + self.schedule_update_ha_state() + + def turn_off(self): + """Turn the switch off.""" + if self._write_to_hub(self._sid, **{self._data_key: 'off'}): + self._state = False + self.schedule_update_ha_state() + + def parse_data(self, data): + """Parse data sent by gateway.""" + if IN_USE in data: + self._in_use = int(data[IN_USE]) + if not self._in_use: + self._load_power = 0 + if POWER_CONSUMED in data: + self._power_consumed = round(float(data[POWER_CONSUMED]), 2) + if LOAD_POWER in data: + self._load_power = round(float(data[LOAD_POWER]), 2) + + value = data.get(self._data_key) + if value is None: + return False + + state = value == 'on' + if self._state == state: + return False + self._state = state + return True diff --git a/homeassistant/components/xiaomi.py b/homeassistant/components/xiaomi.py new file mode 100644 index 00000000000..e4a9698c71f --- /dev/null +++ b/homeassistant/components/xiaomi.py @@ -0,0 +1,195 @@ +"""Support for Xiaomi Gateways.""" +import logging +import voluptuous as vol +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers import discovery +from homeassistant.helpers.entity import Entity +from homeassistant.const import (ATTR_BATTERY_LEVEL, EVENT_HOMEASSISTANT_STOP, + CONF_MAC) + + +REQUIREMENTS = ['https://github.com/Danielhiversen/PyXiaomiGateway/archive/' + '877faec36e1bfa4177cae2a0d4f49570af083e1d.zip#' + 'PyXiaomiGateway==0.1.0'] + +ATTR_GW_SID = 'gw_sid' +ATTR_RINGTONE_ID = 'ringtone_id' +ATTR_RINGTONE_VOL = 'ringtone_vol' +CONF_DISCOVERY_RETRY = 'discovery_retry' +CONF_GATEWAYS = 'gateways' +CONF_INTERFACE = 'interface' +DOMAIN = 'xiaomi' +PY_XIAOMI_GATEWAY = "xiaomi_gw" + + +def _validate_conf(config): + """Validate a list of devices definitions.""" + res_config = [] + for gw_conf in config: + res_gw_conf = {'sid': gw_conf.get(CONF_MAC)} + if res_gw_conf['sid'] is not None: + res_gw_conf['sid'] = res_gw_conf['sid'].replace(":", "").lower() + if len(res_gw_conf['sid']) != 12: + raise vol.Invalid('Invalid mac address', gw_conf.get(CONF_MAC)) + key = gw_conf.get('key') + if key is None: + _LOGGER.warning( + 'Gateway Key is not provided.' + ' Controlling gateway device will not be possible.') + elif len(key) != 16: + raise vol.Invalid('Invalid key %s.' + ' Key must be 16 characters', key) + res_gw_conf['key'] = key + res_config.append(res_gw_conf) + return res_config + + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Optional(CONF_GATEWAYS, default=[{CONF_MAC: None, "key": None}]): + vol.All(cv.ensure_list, _validate_conf), + vol.Optional(CONF_INTERFACE, default='any'): cv.string, + vol.Optional(CONF_DISCOVERY_RETRY, default=3): cv.positive_int + }) +}, extra=vol.ALLOW_EXTRA) + +_LOGGER = logging.getLogger(__name__) + + +def setup(hass, config): + """Set up the Xiaomi component.""" + gateways = config[DOMAIN][CONF_GATEWAYS] + interface = config[DOMAIN][CONF_INTERFACE] + discovery_retry = config[DOMAIN][CONF_DISCOVERY_RETRY] + + from PyXiaomiGateway import PyXiaomiGateway + hass.data[PY_XIAOMI_GATEWAY] = PyXiaomiGateway(hass.add_job, gateways, + interface) + + _LOGGER.debug("Expecting %s gateways", len(gateways)) + for _ in range(discovery_retry): + _LOGGER.info('Discovering Xiaomi Gateways (Try %s)', _ + 1) + hass.data[PY_XIAOMI_GATEWAY].discover_gateways() + if len(hass.data[PY_XIAOMI_GATEWAY].gateways) >= len(gateways): + break + + if not hass.data[PY_XIAOMI_GATEWAY].gateways: + _LOGGER.error("No gateway discovered") + return False + hass.data[PY_XIAOMI_GATEWAY].listen() + _LOGGER.debug("Listening for broadcast") + + for component in ['binary_sensor', 'sensor', 'switch', 'light', 'cover']: + discovery.load_platform(hass, component, DOMAIN, {}, config) + + def stop_xiaomi(event): + """Stop Xiaomi Socket.""" + _LOGGER.info("Shutting down Xiaomi Hub.") + hass.data[PY_XIAOMI_GATEWAY].stop_listen() + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_xiaomi) + + def play_ringtone_service(call): + """Service to play ringtone through Gateway.""" + if call.data.get(ATTR_RINGTONE_ID) is None \ + or call.data.get(ATTR_GW_SID) is None: + _LOGGER.error("Mandatory parameters is not specified.") + return + + ring_id = int(call.data.get(ATTR_RINGTONE_ID)) + if ring_id in [9, 14-19]: + _LOGGER.error('Specified mid: %s is not defined in gateway.', + ring_id) + return + + ring_vol = call.data.get(ATTR_RINGTONE_VOL) + if ring_vol is None: + ringtone = {'mid': ring_id} + else: + ringtone = {'mid': ring_id, 'vol': int(ring_vol)} + + gw_sid = call.data.get(ATTR_GW_SID) + + for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): + if gateway.sid == gw_sid: + gateway.write_to_hub(gateway.sid, **ringtone) + break + else: + _LOGGER.error('Unknown gateway sid: %s was specified.', gw_sid) + + def stop_ringtone_service(call): + """Service to stop playing ringtone on Gateway.""" + gw_sid = call.data.get(ATTR_GW_SID) + if gw_sid is None: + _LOGGER.error("Mandatory parameter (%s) is not specified.", + ATTR_GW_SID) + return + + for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): + if gateway.sid == gw_sid: + ringtone = {'mid': 10000} + gateway.write_to_hub(gateway.sid, **ringtone) + break + else: + _LOGGER.error('Unknown gateway sid: %s was specified.', gw_sid) + + hass.services.async_register(DOMAIN, 'play_ringtone', + play_ringtone_service, + description=None, schema=None) + hass.services.async_register(DOMAIN, 'stop_ringtone', + stop_ringtone_service, + description=None, schema=None) + return True + + +class XiaomiDevice(Entity): + """Representation a base Xiaomi device.""" + + def __init__(self, device, name, xiaomi_hub): + """Initialize the xiaomi device.""" + self._state = None + self._sid = device['sid'] + self._name = '{}_{}'.format(name, self._sid) + self._write_to_hub = xiaomi_hub.write_to_hub + self._get_from_hub = xiaomi_hub.get_from_hub + xiaomi_hub.callbacks[self._sid].append(self.push_data) + self._device_state_attributes = {} + self.parse_data(device['data']) + self.parse_voltage(device['data']) + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def should_poll(self): + """Poll update device status.""" + return False + + @property + def device_state_attributes(self): + """Return the state attributes.""" + return self._device_state_attributes + + def push_data(self, data): + """Push from Hub.""" + _LOGGER.debug("PUSH >> %s: %s", self, data) + if self.parse_data(data) or self.parse_voltage(data): + self.schedule_update_ha_state() + + def parse_voltage(self, data): + """Parse battery level data sent by gateway.""" + if 'voltage' not in data: + return False + max_volt = 3300 + min_volt = 2800 + voltage = data['voltage'] + voltage = min(voltage, max_volt) + voltage = max(voltage, min_volt) + percent = ((voltage - min_volt) / (max_volt - min_volt)) * 100 + self._device_state_attributes[ATTR_BATTERY_LEVEL] = round(percent, 1) + return True + + def parse_data(self, data): + """Parse data sent by gateway.""" + raise NotImplementedError() diff --git a/requirements_all.txt b/requirements_all.txt index 1adc4778eba..8199348b824 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -276,6 +276,9 @@ holidays==0.8.1 # homeassistant.components.camera.onvif http://github.com/tgaugry/suds-passworddigest-py3/archive/86fc50e39b4d2b8997481967d6a7fe1c57118999.zip#suds-passworddigest-py3==0.1.2a +# homeassistant.components.xiaomi +https://github.com/Danielhiversen/PyXiaomiGateway/archive/877faec36e1bfa4177cae2a0d4f49570af083e1d.zip#PyXiaomiGateway==0.1.0 + # homeassistant.components.sensor.dht # https://github.com/adafruit/Adafruit_Python_DHT/archive/da8cddf7fb629c1ef4f046ca44f42523c9cf2d11.zip#Adafruit_DHT==1.3.0 From 718949481f56ebe8c9f5f67b0f57bdf2bdcb1c3c Mon Sep 17 00:00:00 2001 From: namadori Date: Thu, 20 Jul 2017 15:53:06 +0200 Subject: [PATCH 052/118] fix #8263 corrected Adafruit DHT library version from 1.3.0 to 1.3.2 (#8562) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an optional extended description… --- homeassistant/components/sensor/dht.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/dht.py b/homeassistant/components/sensor/dht.py index 1f24a0ee667..6056322cc24 100644 --- a/homeassistant/components/sensor/dht.py +++ b/homeassistant/components/sensor/dht.py @@ -20,7 +20,7 @@ from homeassistant.util.temperature import celsius_to_fahrenheit # Update this requirement to upstream as soon as it supports Python 3. REQUIREMENTS = ['https://github.com/adafruit/Adafruit_Python_DHT/archive/' 'da8cddf7fb629c1ef4f046ca44f42523c9cf2d11.zip' - '#Adafruit_DHT==1.3.0'] + '#Adafruit_DHT==1.3.2'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 8199348b824..86d3d8d60ac 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -280,7 +280,7 @@ http://github.com/tgaugry/suds-passworddigest-py3/archive/86fc50e39b4d2b89974819 https://github.com/Danielhiversen/PyXiaomiGateway/archive/877faec36e1bfa4177cae2a0d4f49570af083e1d.zip#PyXiaomiGateway==0.1.0 # homeassistant.components.sensor.dht -# https://github.com/adafruit/Adafruit_Python_DHT/archive/da8cddf7fb629c1ef4f046ca44f42523c9cf2d11.zip#Adafruit_DHT==1.3.0 +# https://github.com/adafruit/Adafruit_Python_DHT/archive/da8cddf7fb629c1ef4f046ca44f42523c9cf2d11.zip#Adafruit_DHT==1.3.2 # homeassistant.components.media_player.braviatv https://github.com/aparraga/braviarc/archive/0.3.7.zip#braviarc==0.3.7 From a5c0831dc19382a47381d927e6a2210703020be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Thu, 20 Jul 2017 23:04:21 +0200 Subject: [PATCH 053/118] xiaomi bug fix (#8576) --- .../components/binary_sensor/xiaomi.py | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/binary_sensor/xiaomi.py b/homeassistant/components/binary_sensor/xiaomi.py index 14d2ef9b308..216329da9c8 100644 --- a/homeassistant/components/binary_sensor/xiaomi.py +++ b/homeassistant/components/binary_sensor/xiaomi.py @@ -55,10 +55,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class XiaomiBinarySensor(XiaomiDevice, BinarySensorDevice): """Representation of a base XiaomiBinarySensor.""" - def __init__(self, device, name, xiaomi_hub): + def __init__(self, device, name, xiaomi_hub, data_key, device_class): """Initialize the XiaomiSmokeSensor.""" - self._data_key = None - self._device_class = None + self._data_key = data_key + self._device_class = device_class self._should_poll = False self._density = 0 XiaomiDevice.__init__(self, device, name, xiaomi_hub) @@ -89,10 +89,9 @@ class XiaomiNatgasSensor(XiaomiBinarySensor): def __init__(self, device, xiaomi_hub): """Initialize the XiaomiSmokeSensor.""" - self._data_key = 'alarm' self._density = None - self._device_class = 'gas' - XiaomiBinarySensor.__init__(self, device, 'Natgas Sensor', xiaomi_hub) + XiaomiBinarySensor.__init__(self, device, 'Natgas Sensor', xiaomi_hub, + 'alarm', 'gas') @property def device_state_attributes(self): @@ -128,10 +127,9 @@ class XiaomiMotionSensor(XiaomiBinarySensor): def __init__(self, device, hass, xiaomi_hub): """Initialize the XiaomiMotionSensor.""" self._hass = hass - self._data_key = 'status' self._no_motion_since = 0 - self._device_class = 'motion' - XiaomiBinarySensor.__init__(self, device, 'Motion Sensor', xiaomi_hub) + XiaomiBinarySensor.__init__(self, device, 'Motion Sensor', xiaomi_hub, + 'status', 'motion') @property def device_state_attributes(self): @@ -176,11 +174,9 @@ class XiaomiDoorSensor(XiaomiBinarySensor): def __init__(self, device, xiaomi_hub): """Initialize the XiaomiDoorSensor.""" - self._data_key = 'status' self._open_since = 0 - self._device_class = 'opening' XiaomiBinarySensor.__init__(self, device, 'Door Window Sensor', - xiaomi_hub) + xiaomi_hub, 'status', 'opening') @property def device_state_attributes(self): @@ -219,10 +215,9 @@ class XiaomiSmokeSensor(XiaomiBinarySensor): def __init__(self, device, xiaomi_hub): """Initialize the XiaomiSmokeSensor.""" - self._data_key = 'alarm' self._density = 0 - self._device_class = 'smoke' - XiaomiBinarySensor.__init__(self, device, 'Smoke Sensor', xiaomi_hub) + XiaomiBinarySensor.__init__(self, device, 'Smoke Sensor', xiaomi_hub, + 'alarm', 'smoke') @property def device_state_attributes(self): @@ -257,8 +252,8 @@ class XiaomiButton(XiaomiBinarySensor): def __init__(self, device, name, data_key, hass, xiaomi_hub): """Initialize the XiaomiButton.""" self._hass = hass - self._data_key = data_key - XiaomiBinarySensor.__init__(self, device, name, xiaomi_hub) + XiaomiBinarySensor.__init__(self, device, name, xiaomi_hub, + data_key, None) def parse_data(self, data): """Parse data sent by gateway.""" @@ -297,7 +292,8 @@ class XiaomiCube(XiaomiBinarySensor): """Initialize the Xiaomi Cube.""" self._hass = hass self._state = False - XiaomiBinarySensor.__init__(self, device, 'Cube', xiaomi_hub) + XiaomiBinarySensor.__init__(self, device, 'Cube', xiaomi_hub, + None, None) def parse_data(self, data): """Parse data sent by gateway.""" From e63a96cf53ec6f0ed0fad7bf362e262c9943cecb Mon Sep 17 00:00:00 2001 From: Aaron Bach Date: Thu, 20 Jul 2017 16:59:41 -0600 Subject: [PATCH 054/118] Bumped python-simplisafe version (#8578) * Bumped python-simplisafe version --- homeassistant/components/alarm_control_panel/simplisafe.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/simplisafe.py b/homeassistant/components/alarm_control_panel/simplisafe.py index 913a3abb616..a600a01fcfd 100644 --- a/homeassistant/components/alarm_control_panel/simplisafe.py +++ b/homeassistant/components/alarm_control_panel/simplisafe.py @@ -16,7 +16,7 @@ from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP) import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['simplisafe-python==1.0.2'] +REQUIREMENTS = ['simplisafe-python==1.0.3'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 86d3d8d60ac..9110795275d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -843,7 +843,7 @@ sense-hat==2.2.0 sharp_aquos_rc==0.3.2 # homeassistant.components.alarm_control_panel.simplisafe -simplisafe-python==1.0.2 +simplisafe-python==1.0.3 # homeassistant.components.notify.slack slacker==0.9.50 From 4f8d2ec31717305f242ed7d8dfdd76af34ab86dd Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Fri, 21 Jul 2017 03:40:07 -0400 Subject: [PATCH 055/118] Added Time Remaining and Time Elapsed sensors for octoprint (#8581) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an optional extended description… --- homeassistant/components/sensor/octoprint.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/components/sensor/octoprint.py b/homeassistant/components/sensor/octoprint.py index 150a97288cc..035799429f5 100644 --- a/homeassistant/components/sensor/octoprint.py +++ b/homeassistant/components/sensor/octoprint.py @@ -25,6 +25,8 @@ SENSOR_TYPES = { 'Temperatures': ['printer', 'temperature', '*', TEMP_CELSIUS], 'Current State': ['printer', 'state', 'text', None], 'Job Percentage': ['job', 'progress', 'completion', '%'], + 'Time Remaining': ['job', 'progress', 'printTimeLeft', 'seconds'], + 'Time Elapsed': ['job', 'progress', 'printTime', 'seconds'], } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ From f6a5e0887da10418f73bc7df0a76d307e3a9b76a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Fri, 21 Jul 2017 10:10:03 +0200 Subject: [PATCH 056/118] upgade xiaomi lib to 0.2 (#8584) --- homeassistant/components/xiaomi.py | 4 ++-- requirements_all.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/xiaomi.py b/homeassistant/components/xiaomi.py index e4a9698c71f..59fe120ccaf 100644 --- a/homeassistant/components/xiaomi.py +++ b/homeassistant/components/xiaomi.py @@ -9,8 +9,8 @@ from homeassistant.const import (ATTR_BATTERY_LEVEL, EVENT_HOMEASSISTANT_STOP, REQUIREMENTS = ['https://github.com/Danielhiversen/PyXiaomiGateway/archive/' - '877faec36e1bfa4177cae2a0d4f49570af083e1d.zip#' - 'PyXiaomiGateway==0.1.0'] + 'aa9325fe6fdd62a8ef8c9ca1dce31d3292f484bb.zip#' + 'PyXiaomiGateway==0.2.0'] ATTR_GW_SID = 'gw_sid' ATTR_RINGTONE_ID = 'ringtone_id' diff --git a/requirements_all.txt b/requirements_all.txt index 9110795275d..9275e5ed332 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -277,7 +277,7 @@ holidays==0.8.1 http://github.com/tgaugry/suds-passworddigest-py3/archive/86fc50e39b4d2b8997481967d6a7fe1c57118999.zip#suds-passworddigest-py3==0.1.2a # homeassistant.components.xiaomi -https://github.com/Danielhiversen/PyXiaomiGateway/archive/877faec36e1bfa4177cae2a0d4f49570af083e1d.zip#PyXiaomiGateway==0.1.0 +https://github.com/Danielhiversen/PyXiaomiGateway/archive/aa9325fe6fdd62a8ef8c9ca1dce31d3292f484bb.zip#PyXiaomiGateway==0.2.0 # homeassistant.components.sensor.dht # https://github.com/adafruit/Adafruit_Python_DHT/archive/da8cddf7fb629c1ef4f046ca44f42523c9cf2d11.zip#Adafruit_DHT==1.3.2 From fada6d3f493ebf39732834a62bc86e281e3d6d6f Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Fri, 21 Jul 2017 10:13:42 +0200 Subject: [PATCH 057/118] Device support for different new sensors of the xiaomi aqara gateway (#8577) * The gateway configuration accepts a MAC address or a SID value in uppercase already. The ringtone services accepts the same values now. I hope it will avoid confusion. * Device support for the new wall switches with neutral lead (ctrl_ln1, ctrl_ln2) added. * Measurement unit from pressure of weather.v1 fixed. * Device support for sensor_magnet.aq2 added. * Device support for sensor_motion.aq2 (motion and lux) added. * Code reformatted. * The ringtone service (start/stop) uses the parameter gw_mac instead of gw_sid now. * Version of the required library updated. --- homeassistant/components/binary_sensor/xiaomi.py | 4 ++++ homeassistant/components/sensor/xiaomi.py | 9 +++++++-- homeassistant/components/switch/xiaomi.py | 13 +++++++++++++ homeassistant/components/xiaomi.py | 16 +++++++++------- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/binary_sensor/xiaomi.py b/homeassistant/components/binary_sensor/xiaomi.py index 216329da9c8..2f9d91655b6 100644 --- a/homeassistant/components/binary_sensor/xiaomi.py +++ b/homeassistant/components/binary_sensor/xiaomi.py @@ -25,8 +25,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): model = device['model'] if model == 'motion': devices.append(XiaomiMotionSensor(device, hass, gateway)) + elif model == 'sensor_motion.aq2': + devices.append(XiaomiMotionSensor(device, hass, gateway)) elif model == 'magnet': devices.append(XiaomiDoorSensor(device, gateway)) + elif model == 'sensor_magnet.aq2': + devices.append(XiaomiDoorSensor(device, gateway)) elif model == 'smoke': devices.append(XiaomiSmokeSensor(device, gateway)) elif model == 'natgas': diff --git a/homeassistant/components/sensor/xiaomi.py b/homeassistant/components/sensor/xiaomi.py index b1fcd8beb1f..994a6789bbf 100644 --- a/homeassistant/components/sensor/xiaomi.py +++ b/homeassistant/components/sensor/xiaomi.py @@ -17,13 +17,16 @@ def setup_platform(hass, config, add_devices, discovery_info=None): 'temperature', gateway)) devices.append(XiaomiSensor(device, 'Humidity', 'humidity', gateway)) - if device['model'] == 'weather.v1': + elif device['model'] == 'weather.v1': devices.append(XiaomiSensor(device, 'Temperature', 'temperature', gateway)) devices.append(XiaomiSensor(device, 'Humidity', 'humidity', gateway)) devices.append(XiaomiSensor(device, 'Pressure', 'pressure', gateway)) + elif device['model'] == 'sensor_motion.aq2': + devices.append(XiaomiSensor(device, 'Illumination', + 'lux', gateway)) elif device['model'] == 'gateway': devices.append(XiaomiSensor(device, 'Illumination', 'illumination', gateway)) @@ -47,6 +50,8 @@ class XiaomiSensor(XiaomiDevice): return '%' elif self._data_key == 'illumination': return 'lm' + elif self._data_key == 'lux': + return 'lx' elif self._data_key == 'pressure': return 'hPa' @@ -69,7 +74,7 @@ class XiaomiSensor(XiaomiDevice): return False elif self._data_key == 'pressure' and value == 0: return False - if self._data_key in ['temperature', 'humidity']: + if self._data_key in ['temperature', 'humidity', 'pressure']: value /= 100 elif self._data_key in ['illumination']: value = max(value - 300, 0) diff --git a/homeassistant/components/switch/xiaomi.py b/homeassistant/components/switch/xiaomi.py index fa472136bb5..3e4ea4f6d72 100644 --- a/homeassistant/components/switch/xiaomi.py +++ b/homeassistant/components/switch/xiaomi.py @@ -27,6 +27,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): devices.append(XiaomiGenericSwitch(device, 'Wall Switch', 'channel_0', False, gateway)) + elif model == 'ctrl_ln1': + devices.append(XiaomiGenericSwitch(device, 'Wall Switch LN', + 'channel_0', + False, gateway)) elif model == 'ctrl_neutral2': devices.append(XiaomiGenericSwitch(device, 'Wall Switch Left', 'channel_0', @@ -34,6 +38,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None): devices.append(XiaomiGenericSwitch(device, 'Wall Switch Right', 'channel_1', False, gateway)) + elif model == 'ctrl_ln2': + devices.append(XiaomiGenericSwitch(device, + 'Wall Switch LN Left', + 'channel_0', + False, gateway)) + devices.append(XiaomiGenericSwitch(device, + 'Wall Switch LN Right', + 'channel_1', + False, gateway)) elif model == '86plug': devices.append(XiaomiGenericSwitch(device, 'Wall Plug', 'status', True, gateway)) diff --git a/homeassistant/components/xiaomi.py b/homeassistant/components/xiaomi.py index 59fe120ccaf..377446a66c8 100644 --- a/homeassistant/components/xiaomi.py +++ b/homeassistant/components/xiaomi.py @@ -12,7 +12,7 @@ REQUIREMENTS = ['https://github.com/Danielhiversen/PyXiaomiGateway/archive/' 'aa9325fe6fdd62a8ef8c9ca1dce31d3292f484bb.zip#' 'PyXiaomiGateway==0.2.0'] -ATTR_GW_SID = 'gw_sid' +ATTR_GW_MAC = 'gw_mac' ATTR_RINGTONE_ID = 'ringtone_id' ATTR_RINGTONE_VOL = 'ringtone_vol' CONF_DISCOVERY_RETRY = 'discovery_retry' @@ -90,12 +90,13 @@ def setup(hass, config): def play_ringtone_service(call): """Service to play ringtone through Gateway.""" - if call.data.get(ATTR_RINGTONE_ID) is None \ - or call.data.get(ATTR_GW_SID) is None: + ring_id = call.data.get(ATTR_RINGTONE_ID) + gw_sid = call.data.get(ATTR_GW_MAC) + if ring_id is None or gw_sid is None: _LOGGER.error("Mandatory parameters is not specified.") return - ring_id = int(call.data.get(ATTR_RINGTONE_ID)) + ring_id = int(ring_id) if ring_id in [9, 14-19]: _LOGGER.error('Specified mid: %s is not defined in gateway.', ring_id) @@ -107,7 +108,7 @@ def setup(hass, config): else: ringtone = {'mid': ring_id, 'vol': int(ring_vol)} - gw_sid = call.data.get(ATTR_GW_SID) + gw_sid = gw_sid.replace(":", "").lower() for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): if gateway.sid == gw_sid: @@ -118,12 +119,13 @@ def setup(hass, config): def stop_ringtone_service(call): """Service to stop playing ringtone on Gateway.""" - gw_sid = call.data.get(ATTR_GW_SID) + gw_sid = call.data.get(ATTR_GW_MAC) if gw_sid is None: _LOGGER.error("Mandatory parameter (%s) is not specified.", - ATTR_GW_SID) + ATTR_GW_MAC) return + gw_sid = gw_sid.replace(":", "").lower() for (_, gateway) in hass.data[PY_XIAOMI_GATEWAY].gateways.items(): if gateway.sid == gw_sid: ringtone = {'mid': 10000} From ee153062ab3b3d41576ac86ca4d142dd5cb14c58 Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Fri, 21 Jul 2017 04:19:26 -0400 Subject: [PATCH 058/118] Extends Fitbit sensors to track the device battery level (#8583) * Extends Fitbit sensors to track the device battery level * cleanup old stuff * remove update from init --- homeassistant/components/sensor/fitbit.py | 73 +++++++++++++++++------ 1 file changed, 56 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/sensor/fitbit.py b/homeassistant/components/sensor/fitbit.py index 80e452e7b37..0c10d2159ea 100644 --- a/homeassistant/components/sensor/fitbit.py +++ b/homeassistant/components/sensor/fitbit.py @@ -15,9 +15,9 @@ import voluptuous as vol from homeassistant.core import callback from homeassistant.components.http import HomeAssistantView from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import ATTR_ATTRIBUTION from homeassistant.helpers.entity import Entity from homeassistant.loader import get_component -from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['fitbit==0.2.3'] @@ -32,6 +32,7 @@ ATTR_CLIENT_SECRET = 'client_secret' ATTR_LAST_SAVED_AT = 'last_saved_at' CONF_MONITORED_RESOURCES = 'monitored_resources' +CONF_ATTRIBUTION = 'Data provided by Fitbit.com' DEPENDENCIES = ['http'] @@ -40,9 +41,7 @@ FITBIT_AUTH_START = '/auth/fitbit' FITBIT_CONFIG_FILE = 'fitbit.conf' FITBIT_DEFAULT_RESOURCES = ['activities/steps'] -ICON = 'mdi:walk' - -MIN_TIME_BETWEEN_UPDATES = datetime.timedelta(minutes=30) +SCAN_INTERVAL = datetime.timedelta(minutes=30) DEFAULT_CONFIG = { 'client_id': 'CLIENT_ID_HERE', @@ -74,6 +73,7 @@ FITBIT_RESOURCES_LIST = { 'activities/tracker/steps': 'steps', 'body/bmi': 'BMI', 'body/fat': '%', + 'devices/battery': 'level', 'sleep/awakeningsCount': 'times awaken', 'sleep/efficiency': '%', 'sleep/minutesAfterWakeup': 'minutes', @@ -95,6 +95,7 @@ FITBIT_MEASUREMENTS = { 'body': 'in', 'liquids': 'fl. oz.', 'blood glucose': 'mg/dL', + 'battery': '', }, 'en_GB': { 'duration': 'milliseconds', @@ -104,7 +105,8 @@ FITBIT_MEASUREMENTS = { 'weight': 'stone', 'body': 'centimeters', 'liquids': 'milliliters', - 'blood glucose': 'mmol/L' + 'blood glucose': 'mmol/L', + 'battery': '', }, 'metric': { 'duration': 'milliseconds', @@ -114,7 +116,8 @@ FITBIT_MEASUREMENTS = { 'weight': 'kilograms', 'body': 'centimeters', 'liquids': 'milliliters', - 'blood glucose': 'mmol/L' + 'blood glucose': 'mmol/L', + 'battery': '', } } @@ -253,11 +256,20 @@ def setup_platform(hass, config, add_devices, discovery_info=None): authd_client.system = 'en_US' dev = [] + registered_devs = authd_client.get_devices() for resource in config.get(CONF_MONITORED_RESOURCES): - dev.append(FitbitSensor( - authd_client, config_path, resource, - hass.config.units.is_metric)) - add_devices(dev) + + # monitor battery for all linked FitBit devices + if resource == 'devices/battery': + for dev_extra in registered_devs: + dev.append(FitbitSensor( + authd_client, config_path, resource, + hass.config.units.is_metric, dev_extra)) + else: + dev.append(FitbitSensor( + authd_client, config_path, resource, + hass.config.units.is_metric)) + add_devices(dev, True) else: oauth = fitbit.api.FitbitOauth2Client( @@ -348,11 +360,13 @@ class FitbitAuthCallbackView(HomeAssistantView): class FitbitSensor(Entity): """Implementation of a Fitbit sensor.""" - def __init__(self, client, config_path, resource_type, is_metric): + def __init__(self, client, config_path, resource_type, + is_metric, extra=None): """Initialize the Fitbit sensor.""" self.client = client self.config_path = config_path self.resource_type = resource_type + self.extra = extra pretty_resource = self.resource_type.replace('activities/', '') pretty_resource = pretty_resource.replace('/', ' ') pretty_resource = pretty_resource.title() @@ -360,6 +374,13 @@ class FitbitSensor(Entity): pretty_resource = 'BMI' elif pretty_resource == 'Heart': pretty_resource = 'Resting Heart Rate' + elif pretty_resource == 'Devices Battery': + if self.extra: + pretty_resource = \ + '{0} Battery'.format(self.extra.get('deviceVersion')) + else: + pretty_resource = 'Battery' + self._name = pretty_resource unit_type = FITBIT_RESOURCES_LIST[self.resource_type] if unit_type == "": @@ -374,7 +395,6 @@ class FitbitSensor(Entity): unit_type = measurement_system[split_resource[-1]] self._unit_of_measurement = unit_type self._state = 0 - self.update() @property def name(self): @@ -394,14 +414,33 @@ class FitbitSensor(Entity): @property def icon(self): """Icon to use in the frontend, if any.""" - return ICON + if self.resource_type == 'devices/battery': + return 'mdi:battery-50' + return 'mdi:walk' + + @property + def device_state_attributes(self): + """Return the state attributes.""" + attrs = {} + + attrs[ATTR_ATTRIBUTION] = CONF_ATTRIBUTION + + if self.extra: + attrs['model'] = self.extra.get('deviceVersion') + attrs['type'] = self.extra.get('type') + + return attrs - @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Get the latest data from the Fitbit API and update the states.""" - container = self.resource_type.replace("/", "-") - response = self.client.time_series(self.resource_type, period='7d') - self._state = response[container][-1].get('value') + if self.resource_type == 'devices/battery': + response = self.client.get_devices() + self._state = response[0].get('battery') + else: + container = self.resource_type.replace("/", "-") + response = self.client.time_series(self.resource_type, period='7d') + self._state = response[container][-1].get('value') + if self.resource_type == 'activities/heart': self._state = response[container][-1]. \ get('value').get('restingHeartRate') From 4359e0babf74aa6c40a3c6354e6b0d67180f3497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Fri, 21 Jul 2017 12:39:25 +0200 Subject: [PATCH 059/118] xiaomi binary sensor bug fix (#8586) * xiaomi binary sensor bug fig * Is not need on binary_sensor --- homeassistant/components/binary_sensor/xiaomi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/binary_sensor/xiaomi.py b/homeassistant/components/binary_sensor/xiaomi.py index 2f9d91655b6..fafdc098c5d 100644 --- a/homeassistant/components/binary_sensor/xiaomi.py +++ b/homeassistant/components/binary_sensor/xiaomi.py @@ -73,8 +73,8 @@ class XiaomiBinarySensor(XiaomiDevice, BinarySensorDevice): return self._should_poll @property - def state(self): - """Return the state of the sensor.""" + def is_on(self): + """Return true if sensor is on.""" return self._state @property From 06ceadfd543d619bef4fa0aaed5ea1a0c9ff9414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Osb=C3=A4ck?= Date: Fri, 21 Jul 2017 22:35:19 +0200 Subject: [PATCH 060/118] upgrade pywebpush and PyJWT (#8588) --- homeassistant/components/notify/html5.py | 2 +- requirements_all.txt | 4 ++-- requirements_test_all.txt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/notify/html5.py b/homeassistant/components/notify/html5.py index 1fcd2e03898..7151b418248 100644 --- a/homeassistant/components/notify/html5.py +++ b/homeassistant/components/notify/html5.py @@ -25,7 +25,7 @@ from homeassistant.components.http import HomeAssistantView from homeassistant.components.frontend import add_manifest_json_key from homeassistant.helpers import config_validation as cv -REQUIREMENTS = ['pywebpush==1.0.5', 'PyJWT==1.5.0'] +REQUIREMENTS = ['pywebpush==1.0.6', 'PyJWT==1.5.2'] DEPENDENCIES = ['frontend'] diff --git a/requirements_all.txt b/requirements_all.txt index 9275e5ed332..4c9a05aafb3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -21,7 +21,7 @@ astral==1.4 PyISY==1.0.7 # homeassistant.components.notify.html5 -PyJWT==1.5.0 +PyJWT==1.5.2 # homeassistant.components.sensor.mvglive PyMVGLive==1.1.4 @@ -785,7 +785,7 @@ pyvizio==0.0.2 pyvlx==0.1.3 # homeassistant.components.notify.html5 -pywebpush==1.0.5 +pywebpush==1.0.6 # homeassistant.components.wemo pywemo==0.4.19 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 58fdcecf63c..491f5574b32 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -21,7 +21,7 @@ freezegun>=0.3.8 # homeassistant.components.notify.html5 -PyJWT==1.5.0 +PyJWT==1.5.2 # homeassistant.components.media_player.sonos SoCo==0.12 @@ -108,7 +108,7 @@ python-forecastio==1.3.5 pyunifi==2.13 # homeassistant.components.notify.html5 -pywebpush==1.0.5 +pywebpush==1.0.6 # homeassistant.components.python_script restrictedpython==4.0a3 From dc42b6358aa84a8ec7a856c57fd5b01922d5d791 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Fri, 21 Jul 2017 20:18:57 -0400 Subject: [PATCH 061/118] Support for Wink oauth application authorization (#8208) --- .../www_static/images/config_wink.png | Bin 0 -> 8174 bytes homeassistant/components/wink.py | 321 ++++++++++++++---- 2 files changed, 262 insertions(+), 59 deletions(-) create mode 100644 homeassistant/components/frontend/www_static/images/config_wink.png diff --git a/homeassistant/components/frontend/www_static/images/config_wink.png b/homeassistant/components/frontend/www_static/images/config_wink.png new file mode 100644 index 0000000000000000000000000000000000000000..6b91f8cb58ee80f95c0e2277940b629e23a2cfd3 GIT binary patch literal 8174 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 Qfq{X+)78&qol`;+04kp0`~Uy| literal 0 HcmV?d00001 diff --git a/homeassistant/components/wink.py b/homeassistant/components/wink.py index 7024291e7fe..58a6f51b67b 100644 --- a/homeassistant/components/wink.py +++ b/homeassistant/components/wink.py @@ -7,15 +7,21 @@ https://home-assistant.io/components/wink/ import logging import time import json +import os from datetime import timedelta import voluptuous as vol +import requests +from homeassistant.loader import get_component +from homeassistant.core import callback +from homeassistant.components.http import HomeAssistantView from homeassistant.helpers import discovery from homeassistant.helpers.event import track_time_interval from homeassistant.const import ( - CONF_ACCESS_TOKEN, ATTR_BATTERY_LEVEL, CONF_EMAIL, CONF_PASSWORD, - EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP) + ATTR_BATTERY_LEVEL, CONF_EMAIL, CONF_PASSWORD, + EVENT_HOMEASSISTANT_START, + EVENT_HOMEASSISTANT_STOP, __version__) from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv @@ -23,11 +29,10 @@ REQUIREMENTS = ['python-wink==1.3.1', 'pubnubsub-handler==1.0.2'] _LOGGER = logging.getLogger(__name__) -CHANNELS = [] - DOMAIN = 'wink' SUBSCRIPTION_HANDLER = None + CONF_CLIENT_ID = 'client_id' CONF_CLIENT_SECRET = 'client_secret' CONF_USER_AGENT = 'user_agent' @@ -37,8 +42,24 @@ CONF_DEFINED_BOTH_MSG = 'Remove access token to use oath2.' CONF_MISSING_OATH_MSG = 'Missing oath2 credentials.' CONF_TOKEN_URL = "https://winkbearertoken.appspot.com/token" +ATTR_ACCESS_TOKEN = 'access_token' +ATTR_REFRESH_TOKEN = 'refresh_token' +ATTR_CLIENT_ID = 'client_id' +ATTR_CLIENT_SECRET = 'client_secret' + +WINK_AUTH_CALLBACK_PATH = '/auth/wink/callback' +WINK_AUTH_START = '/auth/wink' +WINK_CONFIG_FILE = '.wink.conf' +USER_AGENT = "Manufacturer/Home-Assistant%s python/3 Wink/3" % (__version__) + +DEFAULT_CONFIG = { + 'client_id': 'CLIENT_ID_HERE', + 'client_secret': 'CLIENT_SECRET_HERE' +} + SERVICE_ADD_NEW_DEVICES = 'add_new_devices' SERVICE_REFRESH_STATES = 'refresh_state_from_wink' +SERVICE_KEEP_ALIVE = 'keep_pubnub_updates_flowing' CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ @@ -52,11 +73,6 @@ CONFIG_SCHEMA = vol.Schema({ msg=CONF_MISSING_OATH_MSG): cv.string, vol.Exclusive(CONF_EMAIL, CONF_OATH, msg=CONF_DEFINED_BOTH_MSG): cv.string, - vol.Exclusive(CONF_ACCESS_TOKEN, CONF_OATH, - msg=CONF_DEFINED_BOTH_MSG): cv.string, - vol.Exclusive(CONF_ACCESS_TOKEN, CONF_APPSPOT, - msg=CONF_DEFINED_BOTH_MSG): cv.string, - vol.Optional(CONF_USER_AGENT, default=None): cv.string }) }, extra=vol.ALLOW_EXTRA) @@ -66,30 +82,118 @@ WINK_COMPONENTS = [ ] +def _write_config_file(file_path, config): + try: + with open(file_path, 'w') as conf_file: + conf_file.write(json.dumps(config, sort_keys=True, indent=4)) + except IOError as error: + _LOGGER.error("Saving config file failed: %s", error) + raise IOError("Saving Wink config file failed") + return config + + +def _read_config_file(file_path): + try: + with open(file_path, 'r') as conf_file: + return json.loads(conf_file.read()) + except IOError as error: + _LOGGER.error("Reading config file failed: %s", error) + raise IOError("Reading Wink config file failed") + + +def _request_app_setup(hass, config): + """Assist user with configuring the Wink dev application.""" + hass.data['configurator'] = True + configurator = get_component('configurator') + + # pylint: disable=unused-argument + def wink_configuration_callback(callback_data): + """Handle configuration updates.""" + _config_path = hass.config.path(WINK_CONFIG_FILE) + if not os.path.isfile(_config_path): + setup(hass, config) + return + + client_id = callback_data.get('client_id') + client_secret = callback_data.get('client_secret') + if None not in (client_id, client_secret): + _write_config_file(_config_path, + {ATTR_CLIENT_ID: client_id, + ATTR_CLIENT_SECRET: client_secret}) + setup(hass, config) + return + else: + error_msg = ("Your input was invalid. Please try again.") + _configurator = hass.data[DOMAIN]['configuring'][DOMAIN] + configurator.notify_errors(_configurator, error_msg) + + start_url = "{}{}".format(hass.config.api.base_url, + WINK_AUTH_CALLBACK_PATH) + + description = """Please create a Wink developer app at + https://developer.wink.com. + Add a Redirect URI of {}. + They will provide you a Client ID and secret + after reviewing your request. + (This can take several days). + """.format(start_url) + + hass.data[DOMAIN]['configuring'][DOMAIN] = configurator.request_config( + hass, DOMAIN, wink_configuration_callback, + description=description, submit_caption="submit", + description_image="/static/images/config_wink.png", + fields=[{'id': 'client_id', 'name': 'Client ID', 'type': 'string'}, + {'id': 'client_secret', + 'name': 'Client secret', + 'type': 'string'}] + ) + + +def _request_oauth_completion(hass, config): + """Request user complete Wink OAuth2 flow.""" + hass.data['configurator'] = True + configurator = get_component('configurator') + if DOMAIN in hass.data[DOMAIN]['configuring']: + configurator.notify_errors( + hass.data[DOMAIN]['configuring'][DOMAIN], + "Failed to register, please try again.") + return + + # pylint: disable=unused-argument + def wink_configuration_callback(callback_data): + """Call setup again.""" + setup(hass, config) + + start_url = '{}{}'.format(hass.config.api.base_url, WINK_AUTH_START) + + description = "Please authorize Wink by visiting {}".format(start_url) + + hass.data[DOMAIN]['configuring'][DOMAIN] = configurator.request_config( + hass, DOMAIN, wink_configuration_callback, + description=description + ) + + def setup(hass, config): """Set up the Wink component.""" import pywink - import requests from pubnubsubhandler import PubNubSubscriptionHandler - hass.data[DOMAIN] = {} - hass.data[DOMAIN]['entities'] = [] - hass.data[DOMAIN]['unique_ids'] = [] - hass.data[DOMAIN]['entities'] = {} - - user_agent = config[DOMAIN].get(CONF_USER_AGENT) - - if user_agent: - pywink.set_user_agent(user_agent) - - access_token = config[DOMAIN].get(CONF_ACCESS_TOKEN) - client_id = config[DOMAIN].get('client_id') + if hass.data.get(DOMAIN) is None: + hass.data[DOMAIN] = { + 'unique_ids': [], + 'entities': {}, + 'oauth': {}, + 'configuring': {}, + 'pubnub': None, + 'configurator': False + } def _get_wink_token_from_web(): - email = hass.data[DOMAIN]["oath"]["email"] - password = hass.data[DOMAIN]["oath"]["password"] + _email = hass.data[DOMAIN]["oauth"]["email"] + _password = hass.data[DOMAIN]["oauth"]["password"] - payload = {'username': email, 'password': password} + payload = {'username': _email, 'password': _password} token_response = requests.post(CONF_TOKEN_URL, data=payload) try: token = token_response.text.split(':')[1].split()[0].rstrip('Wink Auth +

{}

""" + + if data.get('code') is not None: + response = self.request_token(data.get('code'), + self.config_file["client_secret"]) + + config_contents = { + ATTR_ACCESS_TOKEN: response['access_token'], + ATTR_REFRESH_TOKEN: response['refresh_token'], + ATTR_CLIENT_ID: self.config_file["client_id"], + ATTR_CLIENT_SECRET: self.config_file["client_secret"] + } + _write_config_file(hass.config.path(WINK_CONFIG_FILE), + config_contents) + + hass.async_add_job(setup, hass, self.config) + + return web.Response(text=html_response.format(response_message), + content_type='text/html') + + error_msg = "No code returned from Wink API" + _LOGGER.error(error_msg) + return web.Response(text=html_response.format(error_msg), + content_type='text/html') + + class WinkDevice(Entity): """Representation a base Wink device.""" From 8d31c5fbf63cff82baf2a0f509ffebd0556199ae Mon Sep 17 00:00:00 2001 From: Russell Cloran Date: Fri, 21 Jul 2017 21:22:43 -0700 Subject: [PATCH 062/118] zha: Update to bellows 0.3.4 (#8594) --- homeassistant/components/zha/__init__.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/zha/__init__.py b/homeassistant/components/zha/__init__.py index e397b7d042a..1b2d46ee72b 100644 --- a/homeassistant/components/zha/__init__.py +++ b/homeassistant/components/zha/__init__.py @@ -14,7 +14,7 @@ from homeassistant import const as ha_const from homeassistant.helpers import discovery, entity from homeassistant.util import slugify -REQUIREMENTS = ['bellows==0.3.2'] +REQUIREMENTS = ['bellows==0.3.4'] DOMAIN = 'zha' diff --git a/requirements_all.txt b/requirements_all.txt index 4c9a05aafb3..6bfc3a70ee6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -92,7 +92,7 @@ batinfo==0.4.2 beautifulsoup4==4.6.0 # homeassistant.components.zha -bellows==0.3.2 +bellows==0.3.4 # homeassistant.components.blink blinkpy==0.6.0 From 7bea69ce83c1bec8f25d9cb86780906598c0e7c5 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 21 Jul 2017 21:29:58 -0700 Subject: [PATCH 063/118] update frontend --- homeassistant/components/frontend/version.py | 13 +++++++------ .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 138122 -> 138190 bytes .../www_static/home-assistant-polymer | 2 +- .../www_static/panels/ha-panel-config.html | 2 +- .../www_static/panels/ha-panel-config.html.gz | Bin 15104 -> 15074 bytes .../www_static/panels/ha-panel-hassio.html | 2 +- .../www_static/panels/ha-panel-hassio.html.gz | Bin 378 -> 409 bytes .../www_static/panels/ha-panel-iframe.html | 2 +- .../www_static/panels/ha-panel-iframe.html.gz | Bin 403 -> 407 bytes .../www_static/panels/ha-panel-map.html | 2 +- .../www_static/panels/ha-panel-map.html.gz | Bin 44245 -> 44197 bytes .../panels/ha-panel-shopping-list.html | 1 + .../panels/ha-panel-shopping-list.html.gz | Bin 0 -> 5303 bytes .../www_static/panels/ha-panel-zwave.html | 2 +- .../www_static/panels/ha-panel-zwave.html.gz | Bin 10611 -> 10543 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2484 -> 2485 bytes 18 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html create mode 100644 homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html.gz diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 67c8bbac817..6ab94fe5a78 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -3,21 +3,22 @@ FINGERPRINTS = { "compatibility.js": "8e4c44b5f4288cc48ec1ba94a9bec812", "core.js": "d4a7cb8c80c62b536764e0e81385f6aa", - "frontend.html": "a7d4cb8260e8094342b5bd8c36c4bf5b", + "frontend.html": "7bd9aa75b2602768e66cf7e20845d7c4", "mdi.html": "e91f61a039ed0a9936e7ee5360da3870", "micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a", "panels/ha-panel-automation.html": "72a5c1856cece8d9246328e84185ab0b", - "panels/ha-panel-config.html": "76853de505d173e82249bf605eb73505", + "panels/ha-panel-config.html": "c0e043028cfa75d6d4dc5e0de0bb6dc1", "panels/ha-panel-dev-event.html": "4886c821235492b1b92739b580d21c61", "panels/ha-panel-dev-info.html": "24e888ec7a8acd0c395b34396e9001bc", "panels/ha-panel-dev-service.html": "ac2c50e486927dc4443e93d79f08c06e", "panels/ha-panel-dev-state.html": "8f1a27c04db6329d31cfcc7d0d6a0869", "panels/ha-panel-dev-template.html": "82cd543177c417e5c6612e07df851e6b", - "panels/ha-panel-hassio.html": "262d31efd9add719e0325da5cf79a096", + "panels/ha-panel-hassio.html": "96d563215cf7bf7b0eeaf8625bafa4ef", "panels/ha-panel-history.html": "35177e2046c9a4191c8f51f8160255ce", - "panels/ha-panel-iframe.html": "d920f0aa3c903680f2f8795e2255daab", + "panels/ha-panel-iframe.html": "238189f21e670b6dcfac937e5ebd7d3b", "panels/ha-panel-kiosk.html": "2ac2df41bd447600692a0054892fc094", "panels/ha-panel-logbook.html": "7c45bd41c146ec38b9938b8a5188bb0d", - "panels/ha-panel-map.html": "d3dae1400ec4e4cd7681d2aa79131d55", - "panels/ha-panel-zwave.html": "2ea2223339d1d2faff478751c2927d11" + "panels/ha-panel-map.html": "b4923812c695dd8a69ad3da380ffe7b4", + "panels/ha-panel-shopping-list.html": "75602d06b41702c8093bd91c10374101", + "panels/ha-panel-zwave.html": "8c8e7844d33163f560e1f691550a8369" } diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index 41e9975e8b3..3205a1d7d4f 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -2,4 +2,4 @@ this._useContent&&u.Logical.saveChildNodes(this)},_setupRoot:function(){this._useContent&&(this._createLocalRoot(),this.dataHost||l(u.Logical.getChildNodes(this)))},_createLocalRoot:function(){this.shadyRoot=this.root,this.shadyRoot._distributionClean=!1,this.shadyRoot._hasDistributed=!1,this.shadyRoot._isShadyRoot=!0,this.shadyRoot._dirtyRoots=[];var e=this.shadyRoot._insertionPoints=!this._notes||this._notes._hasContent?this.shadyRoot.querySelectorAll("content"):[];u.Logical.saveChildNodes(this.shadyRoot);for(var t,o=0;o0?~setTimeout(e,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 +return performance.now()};else var t=function(){return Date.now()};var e=function(t,e,i){this.target=t,this.currentTime=e,this.timelineTime=i,this.type="cancel",this.bubbles=!1,this.cancelable=!1,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){}}(0,e),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 c04830c01a9ce36c9f3097e754d9c329a70302df..baceb29a98504762bb696a9090a16641c8b8df42 100644 GIT binary patch delta 68674 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 \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-config.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-config.html.gz index 8c4cf065663ca29a6f33975991002d845e796bcc..a0745b91349ec77b3bb8846abb57ad2bba6a624f 100644 GIT binary patch delta 1068 zcmZoDdsNCL-_5}Q0!+*s<(HTltV*o4*4QT}80kITKm4VdzE|z`W5?L;`MvXcxZs|S zy;lFE$H{TWKS<5ox^IuRbLE=JpUgDsxk^u$2yMNkpYphQ&D`))dlv3tb-s7qZ~Nlc zt6N@fnYARzyLC>NxazutNxP@K&fVbRQo^1j9QjzvOI$tD?1f3dli2%z6INI9SA^bY z&bxduB}Ddktd#8H_x<;6Za%sFEOqMBF0Iq+v>b2QtZ<8Lw3Nv%nLBUx)2p36OP{AL zx^$>sFEuiKzS*g$Wc}sab)$UsrZFtru{*u$wpd(pU49e8seLicvAZ=jgN*kb{m*}k zPbp-hKrd{aQbF)poL5<-I&{I7X&8>WUt#_j7CH)&_h_NzBL6d@3-Ab9)quG#B?HC1Kp zk|QtfTh%^i@}*E-<}H7%mbbSrV|Z3k8^3#_;rSM48@_w%D_@6jmWZF()PCUEfuvTQ zk81*xE@w^tm;3d}^&j7K#Qt)L&zEU?_UX>u{b35Pl2-0MTeN~V`}u7y_P(uEpM9Qf zo10#rk!5w{#{mI`V=hJADCk;p0Q0+*>L5m=;wPD*uP1tYdQUDfBovoUG8uH z%d1b--T2QVe(LLrcgJeiE#MXB_+S5G%O=^tJ&Hb3HzE$qIr{pYZ^QrJep)-5ALNgoM{Y<6U({k9%RpoIw83(y3+S0a{V#}pI o=eIpydbN1w{fYXsCfigjU{A1c<;Gb{ZvSWBb2DP|{R<2X0J)kUz5oCK delta 1098 zcmaD<+E6Ah-_60X!!#n2i8&)tw;(YuHAgo&KQApaT`!{~H-}*(*Ag>*t-odtp4-jb zu3dV1Ids=a?pp1PO&c4xPu?A5vBLax|A(WE$#KX3SRc4Dy*zcr_05y-nQ7Ed)3USd zjC!k|`nY+`T=kTD0r#2|-)AqseerAPp^_-ypp8qN{7#EAU4Kv%ed4QGgp$&k1D7|& zU7NV3kaubKWF6@eDUDC--q&rox`%zws`rfBUuGC-O>~(4DKVn^om6e}pJyl4?whaI z?~jXH`C^sG6W{c?MibnwYiJv=x9CTdZLZ&AHF4#a2RTs5f|Utu&;fBG7WjEBaJQ9QpB)?b@s_wv(h+glG^ zcf6lk9G|%N@9yvV4(0oMj}`E3-&FFXvUhT4;TjHwMv-U>n-Sxk3 zd-!e9z4CBJ$zAv z8($q^b@yInTkx}TrkQ&9cnWX8rX&NlA9mww9G$J*=F6M4?8eCN#L zU$vi~o@?Z<9+6n_;@OU6|L<$u+22(WB{$E{QuO_&zOBp7FTNh@t#ohuy-#N{f9`&A zBytyDe0i?LNuHY*&b*4b8h!ekonz&yPX`PQKJmv0F>~MQ*vV7$IAZOMlk8g`yZD`Q zJYJ+x7L&S>_saAsI_mowzTs_2A_A?)jx_k1=&^ W&r;G4n_TkyKg09HqJW1N7#IMnDle4) diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.html b/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.html index f339403019b..2ec3ee876b9 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.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-hassio.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.html.gz index 6a1c2905cf0087ed1d383c04a1cd8ff53c21f228..03b8a09f320d02b2f305c7298c4a974c64d689d7 100644 GIT binary patch literal 409 zcmb2|=3oE;Cg#+jgL$_Nc>aopE@#=0{Kib8uaP%;;^_@ccgr}N8n#M!G^jlXUN#xcqk6 z#$7)>n|3Eu<;kDu<2(E+De3S0gNyjDBqua)+?TTE-@h-?)_P)zU(=PkA9Sx?V4ffr z9AEL~9TWgY?YA5#8Z+f*gZxF%b(`|-!~4T&`k40^t^m#y5u!gW>q?9{4t<8 literal 378 zcmb2|=3oE;Cg#+jgIRYB1pbP;E|1-C{fSu5^$VBU_O`HG`nE|YHR-Gpt7r0(Lb1m` z?rY!l-F9Je+PyuJ_oRIn-@Li)BFCy+8KVwA=Z+KAKR+L@tyI6gEUH_7$+2yLPrTf- zHfZ$R^5#wDm&;wL=;qvc_C*zUPp)v~mK$A=>LB z)u-_Fh+Ez}{n&8-^2s7{P7A! z^y_4n@`GRQ*iDp`Z9AKi^mqQjMf_Ki6Ph>9GYYfcwfJ}SNtjyO^? zLATK<)ZgaYkCPS5)(N%6*5_FboRE55xDBVS=581Q3>)RT9Z<&9R>v2_`;S#14vDjkCzPXAUO}dH|)E`Zl lvu~zHqWbpFW%IVb+ \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-iframe.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-iframe.html.gz index ef8727a2ea39a8df7dc1bd2a637ca81ccf735756..afa1e40bf9d16e54864d7f0ac4ae47beeb6ec8db 100644 GIT binary patch literal 407 zcmb2|=3oE;Cg#$h(|NZI1pbINIW)2uD2r=!IW4Ssp}2j4?H2XJ>|HU@IX{?ou6iu> z>w8cNlXC5yvh=jA)>5B1=Ze-atz<24n6$!k8IQ$<_xI&)sB2YRKVkS{^8+i3XHD~T z1s1bgd5SG%KYd2glijuV!J?@gP3bo4wbs8`v(QW1$@OyFu?Z$i>ZXX=HQD%#j`ch2a#yKdL+)d%X%?^e=m&d;LUEkt8r*z{FsW&$rckP^U z=fCKGwPgZ|3mfmmYh8~2AhYnl(LaXP)61TIVye^IFR&!uZ2iVRjryl^JNK@A8e3f- RTf2Tgqo}!u+cqW!1^_rz#c%)s literal 403 zcmb2|=HO8CT^zy0oRO$okeHX6qnnvll$e{Umr;_N!;l(uFiYA{;IHV$0FMKwb_ICd zJYn@@LUbno+mk;QOg$F2b&{LM=F*;<_3OjD3^MbL^Y3Ncn>}&H32RNY05>lFB{SxQ zoO0Ox?s&n$Uui9iYbK2Q;vqk!~8XkX}F{S;G+J}ppOqxcqVPO~Y z%mP-5zD#)>=kCLHX+y0|wDaW;g}eWLuxPaPHOYAT-cylsueutk~P~6w;CslX6-LwDha+w7|Ps>Zh`Cq=v`uySk zK{La|78kKk1#721^qS6bc>723j3~3*$?G2k8}e%D%--($uUY?et!0R`_OEZrzkVJ5 O#}sUpthis.options.maxZoom?this.setZoom(t):this},panInsideBounds:function(t,i){this._enforcingBounds=!0;var e=this.getCenter(),n=this._limitCenter(e,this._zoom,z(t));return e.equals(n)||this.panTo(n,i),this._enforcingBounds=!1,this},invalidateSize:function(t){if(!this._loaded)return this;t=i({animate:!1,pan:!0},!0===t?{animate:!0}:t);var n=this.getSize();this._sizeChanged=!0,this._lastCenter=null;var o=this.getSize(),s=n.divideBy(2).round(),r=o.divideBy(2).round(),a=s.subtract(r);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(e(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:n,newSize:o})):this},stop:function(){return this.setZoom(this._limitZoom(this._zoom)),this.options.zoomSnap||this.fire("viewreset"),this._stop()},locate:function(t){if(t=this._locateOptions=i({timeout:1e4,watch:!1},t),!("geolocation"in navigator))return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var n=e(this._handleGeolocationResponse,this),o=e(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(n,o,t):navigator.geolocation.getCurrentPosition(n,o,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var i=t.code,e=t.message||(1===i?"permission denied":2===i?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:i,message:"Geolocation error: "+e+"."})},_handleGeolocationResponse:function(t){var i=t.coords.latitude,e=t.coords.longitude,n=new M(i,e),o=n.toBounds(t.coords.accuracy),s=this._locateOptions;if(s.setView){var r=this.getBoundsZoom(o);this.setView(n,s.maxZoom?Math.min(r,s.maxZoom):r)}var a={latlng:n,bounds:o,timestamp:t.timestamp};for(var h in t.coords)"number"==typeof t.coords[h]&&(a[h]=t.coords[h]);this.fire("locationfound",a)},addHandler:function(t,i){if(!i)return this;var e=this[t]=new i(this);return this._handlers.push(e),this.options[t]&&e.enable(),this},remove:function(){if(this._initEvents(!0),this._containerId!==this._container._leaflet_id)throw new Error("Map container is being reused by another instance");try{delete this._container._leaflet_id,delete this._containerId}catch(t){this._container._leaflet_id=void 0,this._containerId=void 0}ut(this._mapPane),this._clearControlPos&&this._clearControlPos(),this._clearHandlers(),this._loaded&&this.fire("unload");var t;for(t in this._layers)this._layers[t].remove();for(t in this._panes)ut(this._panes[t]);return this._layers=[],this._panes=[],delete this._mapPane,delete this._renderer,this},createPane:function(t,i){var e="leaflet-pane"+(t?" leaflet-"+t.replace("Pane","")+"-pane":""),n=ht("div",e,i||this._mapPane);return t&&(this._panes[t]=n),n},getCenter:function(){return this._checkIfLoaded(),this._lastCenter&&!this._moved()?this._lastCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds();return new T(this.unproject(t.getBottomLeft()),this.unproject(t.getTopRight()))},getMinZoom:function(){return void 0===this.options.minZoom?this._layersMinZoom||0:this.options.minZoom},getMaxZoom:function(){return void 0===this.options.maxZoom?void 0===this._layersMaxZoom?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,i,e){t=z(t),e=w(e||[0,0]);var n=this.getZoom()||0,o=this.getMinZoom(),s=this.getMaxZoom(),r=t.getNorthWest(),a=t.getSouthEast(),h=this.getSize().subtract(e),u=b(this.project(a,n),this.project(r,n)).getSize(),l=Ki?this.options.zoomSnap:1,c=h.x/u.x,_=h.y/u.y,d=i?Math.max(c,_):Math.min(c,_);return n=this.getScaleZoom(d,n),l&&(n=Math.round(n/(l/100))*(l/100),n=i?Math.ceil(n/l)*l:Math.floor(n/l)*l),Math.max(o,Math.min(s,n))},getSize:function(){return this._size&&!this._sizeChanged||(this._size=new x(this._container.clientWidth||0,this._container.clientHeight||0),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(t,i){var e=this._getTopLeftPoint(t,i);return new P(e,e.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._pixelOrigin},getPixelWorldBounds:function(t){return this.options.crs.getProjectedBounds(void 0===t?this.getZoom():t)},getPane:function(t){return"string"==typeof t?this._panes[t]:t},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t,i){var e=this.options.crs;return i=void 0===i?this._zoom:i,e.scale(t)/e.scale(i)},getScaleZoom:function(t,i){var e=this.options.crs;i=void 0===i?this._zoom:i;var n=e.zoom(t*e.scale(i));return isNaN(n)?1/0:n},project:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.latLngToPoint(C(t),i)},unproject:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.pointToLatLng(w(t),i)},layerPointToLatLng:function(t){var i=w(t).add(this.getPixelOrigin());return this.unproject(i)},latLngToLayerPoint:function(t){return this.project(C(t))._round()._subtract(this.getPixelOrigin())},wrapLatLng:function(t){return this.options.crs.wrapLatLng(C(t))},wrapLatLngBounds:function(t){return this.options.crs.wrapLatLngBounds(z(t))},distance:function(t,i){return this.options.crs.distance(C(t),C(i))},containerPointToLayerPoint:function(t){return w(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return w(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var i=this.containerPointToLayerPoint(w(t));return this.layerPointToLatLng(i)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(C(t)))},mouseEventToContainerPoint:function(t){return tt(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var i=this._container=rt(t);if(!i)throw new Error("Map container not found.");if(i._leaflet_id)throw new Error("Map container is already initialized.");V(i,"scroll",this._onScroll,this),this._containerId=n(i)},_initLayout:function(){var t=this._container;this._fadeAnimated=this.options.fadeAnimation&&Ki,pt(t,"leaflet-container"+(te?" leaflet-touch":"")+(ne?" leaflet-retina":"")+(Bi?" leaflet-oldie":"")+(Wi?" leaflet-safari":"")+(this._fadeAnimated?" leaflet-fade-anim":""));var i=at(t,"position");"absolute"!==i&&"relative"!==i&&"fixed"!==i&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._paneRenderers={},this._mapPane=this.createPane("mapPane",this._container),Lt(this._mapPane,new x(0,0)),this.createPane("tilePane"),this.createPane("shadowPane"),this.createPane("overlayPane"),this.createPane("markerPane"),this.createPane("tooltipPane"),this.createPane("popupPane"),this.options.markerZoomAnimation||(pt(t.markerPane,"leaflet-zoom-hide"),pt(t.shadowPane,"leaflet-zoom-hide"))},_resetView:function(t,i){Lt(this._mapPane,new x(0,0));var e=!this._loaded;this._loaded=!0,i=this._limitZoom(i),this.fire("viewprereset");var n=this._zoom!==i;this._moveStart(n)._move(t,i)._moveEnd(n),this.fire("viewreset"),e&&this.fire("load")},_moveStart:function(t){return t&&this.fire("zoomstart"),this.fire("movestart")},_move:function(t,i,e){void 0===i&&(i=this._zoom);var n=this._zoom!==i;return this._zoom=i,this._lastCenter=t,this._pixelOrigin=this._getNewPixelOrigin(t),(n||e&&e.pinch)&&this.fire("zoom",e),this.fire("move",e)},_moveEnd:function(t){return t&&this.fire("zoomend"),this.fire("moveend")},_stop:function(){return g(this._flyToFrame),this._panAnim&&this._panAnim.stop(),this},_rawPanBy:function(t){Lt(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_panInsideMaxBounds:function(){this._enforcingBounds||this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(t){this._targets={},this._targets[n(this._container)]=this;var i=t?G:V;i(this._container,"click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress",this._handleDOMEvent,this),this.options.trackResize&&i(window,"resize",this._onResize,this),Ki&&this.options.transform3DLimit&&(t?this.off:this.on).call(this,"moveend",this._onMoveEnd)},_onResize:function(){g(this._resizeRequest),this._resizeRequest=f(function(){this.invalidateSize({debounceMoveend:!0})},this)},_onScroll:function(){this._container.scrollTop=0,this._container.scrollLeft=0},_onMoveEnd:function(){var t=this._getMapPanePos();Math.max(Math.abs(t.x),Math.abs(t.y))>=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,i){for(var e,o=[],s="mouseout"===i||"mouseover"===i,r=t.target||t.srcElement,a=!1;r;){if((e=this._targets[n(r)])&&("click"===i||"preclick"===i)&&!t._simulated&&this._draggableMoved(e)){a=!0;break}if(e&&e.listens(i,!0)){if(s&&!ot(r,t))break;if(o.push(e),s)break}if(r===this._container)break;r=r.parentNode}return o.length||a||s||!ot(r,t)||(o=[this]),o},_handleDOMEvent:function(t){if(this._loaded&&!nt(t)){var i=t.type;"mousedown"!==i&&"keypress"!==i||zt(t.target||t.srcElement),this._fireDOMEvent(t,i)}},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,e,n){if("click"===t.type){var o=i({},t);o.type="preclick",this._fireDOMEvent(o,o.type,n)}if(!t._stopped&&(n=(n||[]).concat(this._findEventTargets(t,e)),n.length)){var s=n[0];"contextmenu"===e&&s.listens(e,!0)&&$(t);var r={originalEvent:t};if("keypress"!==t.type){var a=s.options&&"icon"in s.options;r.containerPoint=a?this.latLngToContainerPoint(s.getLatLng()):this.mouseEventToContainerPoint(t),r.layerPoint=this.containerPointToLayerPoint(r.containerPoint),r.latlng=a?s.getLatLng():this.layerPointToLatLng(r.layerPoint)}for(var h=0;h0?Math.round(t-i)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(i))},_limitZoom:function(t){var i=this.getMinZoom(),e=this.getMaxZoom(),n=Ki?this.options.zoomSnap:1;return n&&(t=Math.round(t/n)*n),Math.max(i,Math.min(e,t))},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){mt(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,i){var e=this._getCenterOffset(t)._floor();return!(!0!==(i&&i.animate)&&!this.getSize().contains(e)||(this.panBy(e,i),0))},_createAnimProxy:function(){var t=this._proxy=ht("div","leaflet-proxy leaflet-zoom-animated");this._panes.mapPane.appendChild(t),this.on("zoomanim",function(t){var i=Pe,e=this._proxy.style[i];wt(this._proxy,this.project(t.center,t.zoom),this.getZoomScale(t.zoom,1)),e===this._proxy.style[i]&&this._animatingZoom&&this._onZoomTransitionEnd()},this),this.on("load moveend",function(){var t=this.getCenter(),i=this.getZoom();wt(this._proxy,this.project(t,i),this.getZoomScale(i,1))},this),this._on("unload",this._destroyAnimProxy,this)},_destroyAnimProxy:function(){ut(this._proxy),delete this._proxy},_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,i,e){if(this._animatingZoom)return!0;if(e=e||{},!this._zoomAnimated||!1===e.animate||this._nothingToAnimate()||Math.abs(i-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(i),o=this._getCenterOffset(t)._divideBy(1-1/n);return!(!0!==e.animate&&!this.getSize().contains(o)||(f(function(){this._moveStart(!0)._animateZoom(t,i,!0)},this),0))},_animateZoom:function(t,i,n,o){n&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=i,pt(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:i,noUpdate:o}),setTimeout(e(this._onZoomTransitionEnd,this),250)},_onZoomTransitionEnd:function(){this._animatingZoom&&(mt(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom),f(function(){this._moveEnd(!0)},this))}}),ke=v.extend({options:{position:"topright"},initialize:function(t){l(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var i=this._map;return i&&i.removeControl(this),this.options.position=t,i&&i.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var i=this._container=this.onAdd(t),e=this.getPosition(),n=t._controlCorners[e];return pt(i,"leaflet-control"),-1!==e.indexOf("bottom")?n.insertBefore(i,n.firstChild):n.appendChild(i),this},remove:function(){return this._map?(ut(this._container),this.onRemove&&this.onRemove(this._map),this._map=null,this):this},_refocusOnMap:function(t){this._map&&t&&t.screenX>0&&t.screenY>0&&this._map.getContainer().focus()}}),Be=function(t){return new ke(t)};Se.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.remove(),this},_initControlPos:function(){function t(t,o){var s=e+t+" "+e+o;i[t+o]=ht("div",s,n)}var i=this._controlCorners={},e="leaflet-",n=this._controlContainer=ht("div",e+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){for(var t in this._controlCorners)ut(this._controlCorners[t]);ut(this._controlContainer),delete this._controlCorners,delete this._controlContainer}});var Ie=ke.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0,hideSingleBase:!1,sortLayers:!1,sortFunction:function(t,i,e,n){return e1,this._baseLayersList.style.display=t?"":"none"),this._separator.style.display=i&&t?"":"none",this},_onLayerChange:function(t){this._handlingClick||this._update();var i=this._getLayer(n(t.target)),e=i.overlay?"add"===t.type?"overlayadd":"overlayremove":"add"===t.type?"baselayerchange":null;e&&this._map.fire(e,i)},_createRadioElement:function(t,i){var e='",n=document.createElement("div");return n.innerHTML=e,n.firstChild},_addItem:function(t){var i,e=document.createElement("label"),o=this._map.hasLayer(t.layer);t.overlay?(i=document.createElement("input"),i.type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=o):i=this._createRadioElement("leaflet-base-layers",o),this._layerControlInputs.push(i),i.layerId=n(t.layer),V(i,"click",this._onInputClick,this);var s=document.createElement("span");s.innerHTML=" "+t.name;var r=document.createElement("div");return e.appendChild(r),r.appendChild(i),r.appendChild(s),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(e),this._checkDisabledLayers(),e},_onInputClick:function(){var t,i,e,n=this._layerControlInputs,o=[],s=[];this._handlingClick=!0;for(var r=n.length-1;r>=0;r--)t=n[r],i=this._getLayer(t.layerId).layer,e=this._map.hasLayer(i),t.checked&&!e?o.push(i):!t.checked&&e&&s.push(i);for(r=0;r=0;o--)t=e[o],i=this._getLayer(t.layerId).layer,t.disabled=void 0!==i.options.minZoom&&ni.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expand:function(){return this.expand()},_collapse:function(){return this.collapse()}}),Ae=function(t,i,e){return new Ie(t,i,e)},Oe=ke.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"−",zoomOutTitle:"Zoom out"},onAdd:function(t){var i="leaflet-control-zoom",e=ht("div",i+" leaflet-bar"),n=this.options;return this._zoomInButton=this._createButton(n.zoomInText,n.zoomInTitle,i+"-in",e,this._zoomIn),this._zoomOutButton=this._createButton(n.zoomOutText,n.zoomOutTitle,i+"-out",e,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),e},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,i,e,n,o){var s=ht("a",e,n);return s.innerHTML=t,s.href="#",s.title=i,s.setAttribute("role","button"),s.setAttribute("aria-label",i),J(s),V(s,"click",Q),V(s,"click",o,this),V(s,"click",this._refocusOnMap,this),s},_updateDisabled:function(){var t=this._map,i="leaflet-disabled";mt(this._zoomInButton,i),mt(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMinZoom())&&pt(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMaxZoom())&&pt(this._zoomInButton,i)}});Se.mergeOptions({zoomControl:!0}),Se.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new Oe,this.addControl(this.zoomControl))});var Re=function(t){return new Oe(t)},De=ke.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var i="leaflet-control-scale",e=ht("div",i),n=this.options;return this._addScales(n,i+"-line",e),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),e},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,i,e){t.metric&&(this._mScale=ht("div",i,e)),t.imperial&&(this._iScale=ht("div",i,e))},_update:function(){var t=this._map,i=t.getSize().y/2,e=t.distance(t.containerPointToLatLng([0,i]),t.containerPointToLatLng([this.options.maxWidth,i]));this._updateScales(e)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var i=this._getRoundNum(t),e=i<1e3?i+" m":i/1e3+" km";this._updateScale(this._mScale,e,i/t)},_updateImperial:function(t){var i,e,n,o=3.2808399*t;o>5280?(i=o/5280,e=this._getRoundNum(i),this._updateScale(this._iScale,e+" mi",e/i)):(n=this._getRoundNum(o),this._updateScale(this._iScale,n+" ft",n/o))},_updateScale:function(t,i,e){t.style.width=Math.round(this.options.maxWidth*e)+"px",t.innerHTML=i},_getRoundNum:function(t){var i=Math.pow(10,(Math.floor(t)+"").length-1),e=t/i;return e=e>=10?10:e>=5?5:e>=3?3:e>=2?2:1,i*e}}),Ne=function(t){return new De(t)},je=ke.extend({options:{position:"bottomright",prefix:'Leaflet'},initialize:function(t){l(this,t),this._attributions={}},onAdd:function(t){t.attributionControl=this,this._container=ht("div","leaflet-control-attribution"),J(this._container);for(var i in t._layers)t._layers[i].getAttribution&&this.addAttribution(t._layers[i].getAttribution());return this._update(),this._container},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):this},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):this},_update:function(){if(this._map){var t=[];for(var i in this._attributions)this._attributions[i]&&t.push(i);var e=[];this.options.prefix&&e.push(this.options.prefix),t.length&&e.push(t.join(", ")),this._container.innerHTML=e.join(" | ")}}});Se.mergeOptions({attributionControl:!0}),Se.addInitHook(function(){this.options.attributionControl&&(new je).addTo(this)});var We=function(t){return new je(t)};ke.Layers=Ie,ke.Zoom=Oe,ke.Scale=De,ke.Attribution=je,Be.layers=Ae,Be.zoom=Re,Be.scale=Ne,Be.attribution=We;var He,Fe=v.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled?this:(this._enabled=!0,this.addHooks(),this)},disable:function(){return this._enabled?(this._enabled=!1,this.removeHooks(),this):this},enabled:function(){return!!this._enabled}}),Ue={Events:xi},Ve=!1,Ge=te?"touchstart mousedown":"mousedown",qe={mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},Ke={mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"},Ye=wi.extend({options:{clickTolerance:3},initialize:function(t,i,e,n){l(this,n),this._element=t,this._dragStartTarget=i||t,this._preventOutline=e},enable:function(){this._enabled||(V(this._dragStartTarget,Ge,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(L.Draggable._dragging===this&&this.finishDrag(),G(this._dragStartTarget,Ge,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){if(!t._simulated&&this._enabled&&(this._moved=!1,!dt(this._element,"leaflet-zoom-anim")&&!(Ve||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(Ve=this,this._preventOutline&&zt(this._element),bt(),zi(),this._moving)))){this.fire("down");var i=t.touches?t.touches[0]:t;this._startPoint=new x(i.clientX,i.clientY),V(document,Ke[t.type],this._onMove,this),V(document,qe[t.type],this._onUp,this)}},_onMove:function(t){if(!t._simulated&&this._enabled){if(t.touches&&t.touches.length>1)return void(this._moved=!0);var i=t.touches&&1===t.touches.length?t.touches[0]:t,e=new x(i.clientX,i.clientY),n=e.subtract(this._startPoint);(n.x||n.y)&&(Math.abs(n.x)+Math.abs(n.y)1e-7;h++)i=s*Math.sin(a),i=Math.pow((1-i)/(1+i),s/2),u=Math.PI/2-2*Math.atan(r*i)-a,a+=u;return new M(a*e,t.x*e/n)}},tn=(Object.freeze||Object)({LonLat:$e,Mercator:Qe,SphericalMercator:bi}),en=i({},Pi,{code:"EPSG:3395",projection:Qe,transformation:function(){var t=.5/(Math.PI*Qe.R);return E(t,.5,-t,.5)}()}),nn=i({},Pi,{code:"EPSG:4326",projection:$e,transformation:E(1/180,1,-1/180,.5)}),on=i({},Li,{projection:$e,transformation:E(1,0,-1,0),scale:function(t){return Math.pow(2,t)},zoom:function(t){return Math.log(t)/Math.LN2},distance:function(t,i){var e=i.lng-t.lng,n=i.lat-t.lat;return Math.sqrt(e*e+n*n)},infinite:!0});Li.Earth=Pi,Li.EPSG3395=en,Li.EPSG3857=Zi,Li.EPSG900913=Ei,Li.EPSG4326=nn,Li.Simple=on;var sn=wi.extend({options:{pane:"overlayPane",attribution:null,bubblingMouseEvents:!0},addTo:function(t){return t.addLayer(this),this},remove:function(){return this.removeFrom(this._map||this._mapToAdd)},removeFrom:function(t){return t&&t.removeLayer(this),this},getPane:function(t){return this._map.getPane(t?this.options[t]||t:this.options.pane)},addInteractiveTarget:function(t){return this._map._targets[n(t)]=this,this}, removeInteractiveTarget:function(t){return delete this._map._targets[n(t)],this},getAttribution:function(){return this.options.attribution},_layerAdd:function(t){var i=t.target;if(i.hasLayer(this)){if(this._map=i,this._zoomAnimated=i._zoomAnimated,this.getEvents){var e=this.getEvents();i.on(e,this),this.once("remove",function(){i.off(e,this)},this)}this.onAdd(i),this.getAttribution&&i.attributionControl&&i.attributionControl.addAttribution(this.getAttribution()),this.fire("add"),i.fire("layeradd",{layer:this})}}});Se.include({addLayer:function(t){var i=n(t);return this._layers[i]?this:(this._layers[i]=t,t._mapToAdd=this,t.beforeAdd&&t.beforeAdd(this),this.whenReady(t._layerAdd,t),this)},removeLayer:function(t){var i=n(t);return this._layers[i]?(this._loaded&&t.onRemove(this),t.getAttribution&&this.attributionControl&&this.attributionControl.removeAttribution(t.getAttribution()),delete this._layers[i],this._loaded&&(this.fire("layerremove",{layer:t}),t.fire("remove")),t._map=t._mapToAdd=null,this):this},hasLayer:function(t){return!!t&&n(t)in this._layers},eachLayer:function(t,i){for(var e in this._layers)t.call(i,this._layers[e]);return this},_addLayers:function(t){t=t?pi(t)?t:[t]:[];for(var i=0,e=t.length;ithis._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()i)return r=(n-i)/e,this._map.layerPointToLatLng([s.x-r*(s.x-o.x),s.y-r*(s.y-o.y)])},getBounds:function(){return this._bounds},addLatLng:function(t,i){return i=i||this._defaultShape(),t=C(t),i.push(t),this._bounds.extend(t),this.redraw()},_setLatLngs:function(t){this._bounds=new T,this._latlngs=this._convertLatLngs(t)},_defaultShape:function(){return jt(this._latlngs)?this._latlngs:this._latlngs[0]},_convertLatLngs:function(t){for(var i=[],e=jt(t),n=0,o=t.length;n=2&&i[0]instanceof M&&i[0].equals(i[e-1])&&i.pop(),i},_setLatLngs:function(t){gn.prototype._setLatLngs.call(this,t),jt(this._latlngs)&&(this._latlngs=[this._latlngs])},_defaultShape:function(){return jt(this._latlngs[0])?this._latlngs[0]:this._latlngs[0][0]},_clipPoints:function(){var t=this._renderer._bounds,i=this.options.weight,e=new x(i,i);if(t=new P(t.min.subtract(e),t.max.add(e)),this._parts=[],this._pxBounds&&this._pxBounds.intersects(t)){if(this.options.noClip)return void(this._parts=this._rings);for(var n,o=0,s=this._rings.length;ot.y!=n.y>t.y&&t.x<(n.x-e.x)*(t.y-e.y)/(n.y-e.y)+e.x&&(u=!u);return u||gn.prototype._containsPoint.call(this,t,!0)}}),yn=hn.extend({initialize:function(t,i){l(this,i),this._layers={},t&&this.addData(t)},addData:function(t){var i,e,n,o=pi(t)?t:t.features;if(o){for(i=0,e=o.length;io?(i.height=o+"px",pt(t,s)):mt(t,s),this._containerWidth=this._container.offsetWidth},_animateZoom:function(t){var i=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center),e=this._getAnchor();Lt(this._container,i.add(e))},_adjustPan:function(){if(!(!this.options.autoPan||this._map._panAnim&&this._map._panAnim._inProgress)){var t=this._map,i=parseInt(at(this._container,"marginBottom"),10)||0,e=this._container.offsetHeight+i,n=this._containerWidth,o=new x(this._containerLeft,-e-this._containerBottom);o._add(Pt(this._container));var s=t.layerPointToContainerPoint(o),r=w(this.options.autoPanPadding),a=w(this.options.autoPanPaddingTopLeft||r),h=w(this.options.autoPanPaddingBottomRight||r),u=t.getSize(),l=0,c=0;s.x+n+h.x>u.x&&(l=s.x+n-u.x+h.x),s.x-l-a.x<0&&(l=s.x-a.x),s.y+e+h.y>u.y&&(c=s.y+e-u.y+h.y),s.y-c-a.y<0&&(c=s.y-a.y),(l||c)&&t.fire("autopanstart").panBy([l,c])}},_onCloseButtonClick:function(t){this._close(),Q(t)},_getAnchor:function(){return w(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}}),Mn=function(t,i){return new zn(t,i)};Se.mergeOptions({closePopupOnClick:!0}),Se.include({openPopup:function(t,i,e){return t instanceof zn||(t=new zn(e).setContent(t)),i&&t.setLatLng(i),this.hasLayer(t)?this:(this._popup&&this._popup.options.autoClose&&this.closePopup(),this._popup=t,this.addLayer(t))},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&this.removeLayer(t),this}}),sn.include({bindPopup:function(t,i){return t instanceof zn?(l(t,i),this._popup=t,t._source=this):(this._popup&&!i||(this._popup=new zn(i,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t,i){if(t instanceof sn||(i=t,t=this),t instanceof hn)for(var e in this._layers){t=this._layers[e];break}return i||(i=t.getCenter?t.getCenter():t.getLatLng()),this._popup&&this._map&&(this._popup._source=t,this._popup.update(),this._map.openPopup(this._popup,i)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(t){return this._popup&&(this._popup._map?this.closePopup():this.openPopup(t)),this},isPopupOpen:function(){return!!this._popup&&this._popup.isOpen()},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},getPopup:function(){return this._popup},_openPopup:function(t){var i=t.layer||t.target;if(this._popup&&this._map)return Q(t),i instanceof pn?void this.openPopup(t.layer||t.target,t.latlng):void(this._map.hasLayer(this._popup)&&this._popup._source===i?this.closePopup():this.openPopup(i,t.latlng))},_movePopup:function(t){this._popup.setLatLng(t.latlng)},_onKeyPress:function(t){13===t.originalEvent.keyCode&&this._openPopup(t)}});var Cn=Tn.extend({options:{pane:"tooltipPane",offset:[0,0],direction:"auto",permanent:!1,sticky:!1,interactive:!1,opacity:.9},onAdd:function(t){Tn.prototype.onAdd.call(this,t),this.setOpacity(this.options.opacity),t.fire("tooltipopen",{tooltip:this}),this._source&&this._source.fire("tooltipopen",{tooltip:this},!0)},onRemove:function(t){Tn.prototype.onRemove.call(this,t),t.fire("tooltipclose",{tooltip:this}),this._source&&this._source.fire("tooltipclose",{tooltip:this},!0)},getEvents:function(){var t=Tn.prototype.getEvents.call(this);return te&&!this.options.permanent&&(t.preclick=this._close),t},_close:function(){this._map&&this._map.closeTooltip(this)},_initLayout:function(){var t="leaflet-tooltip "+(this.options.className||"")+" leaflet-zoom-"+(this._zoomAnimated?"animated":"hide");this._contentNode=this._container=ht("div",t)},_updateLayout:function(){},_adjustPan:function(){},_setPosition:function(t){var i=this._map,e=this._container,n=i.latLngToContainerPoint(i.getCenter()),o=i.layerPointToContainerPoint(t),s=this.options.direction,r=e.offsetWidth,a=e.offsetHeight,h=w(this.options.offset),u=this._getAnchor();"top"===s?t=t.add(w(-r/2+h.x,-a+h.y+u.y,!0)):"bottom"===s?t=t.subtract(w(r/2-h.x,-h.y,!0)):"center"===s?t=t.subtract(w(r/2+h.x,a/2-u.y+h.y,!0)):"right"===s||"auto"===s&&o.xthis.options.maxZoom||en&&this._retainParent(o,s,r,n))},_retainChildren:function(t,i,e,n){for(var o=2*t;o<2*t+2;o++)for(var s=2*i;s<2*i+2;s++){var r=new x(o,s);r.z=e+1;var a=this._tileCoordsToKey(r),h=this._tiles[a];h&&h.active?h.retain=!0:(h&&h.loaded&&(h.retain=!0),e+1this.options.maxZoom||void 0!==this.options.minZoom&&o1)return void this._setView(t,e);for(var c=o.min.y;c<=o.max.y;c++)for(var _=o.min.x;_<=o.max.x;_++){var d=new x(_,c);d.z=this._tileZoom,this._isValidTile(d)&&(this._tiles[this._tileCoordsToKey(d)]||r.push(d))}if(r.sort(function(t,i){return t.distanceTo(s)-i.distanceTo(s)}),0!==r.length){this._loading||(this._loading=!0,this.fire("loading"));var p=document.createDocumentFragment();for(_=0;_e.max.x)||!i.wrapLat&&(t.ye.max.y))return!1}if(!this.options.bounds)return!0;var n=this._tileCoordsToBounds(t);return z(this.options.bounds).overlaps(n)},_keyToBounds:function(t){return this._tileCoordsToBounds(this._keyToTileCoords(t))},_tileCoordsToBounds:function(t){var i=this._map,e=this.getTileSize(),n=t.scaleBy(e),o=n.add(e),s=i.unproject(n,t.z),r=i.unproject(o,t.z),a=new T(s,r);return this.options.noWrap||i.wrapLatLngBounds(a),a},_tileCoordsToKey:function(t){return t.x+":"+t.y+":"+t.z},_keyToTileCoords:function(t){var i=t.split(":"),e=new x(+i[0],+i[1]);return e.z=+i[2],e},_removeTile:function(t){var i=this._tiles[t];i&&(ut(i.el),delete this._tiles[t],this.fire("tileunload",{tile:i.el,coords:this._keyToTileCoords(t)}))},_initTile:function(t){pt(t,"leaflet-tile");var i=this.getTileSize();t.style.width=i.x+"px",t.style.height=i.y+"px",t.onselectstart=r,t.onmousemove=r,Bi&&this.options.opacity<1&&vt(t,this.options.opacity),Oi&&!Ri&&(t.style.WebkitBackfaceVisibility="hidden")},_addTile:function(t,i){var n=this._getTilePos(t),o=this._tileCoordsToKey(t),s=this.createTile(this._wrapCoords(t),e(this._tileReady,this,t));this._initTile(s),this.createTile.length<2&&f(e(this._tileReady,this,t,null,s)),Lt(s,n),this._tiles[o]={el:s,coords:t,current:!0},i.appendChild(s),this.fire("tileloadstart",{tile:s,coords:t})},_tileReady:function(t,i,n){if(this._map){i&&this.fire("tileerror",{error:i,tile:n,coords:t});var o=this._tileCoordsToKey(t);(n=this._tiles[o])&&(n.loaded=+new Date,this._map._fadeAnimated?(vt(n.el,0),g(this._fadeFrame),this._fadeFrame=f(this._updateOpacity,this)):(n.active=!0,this._pruneTiles()),i||(pt(n.el,"leaflet-tile-loaded"),this.fire("tileload",{tile:n.el,coords:t})),this._noTilesToLoad()&&(this._loading=!1,this.fire("load"),Bi||!this._map._fadeAnimated?f(this._pruneTiles,this):setTimeout(e(this._pruneTiles,this),250)))}},_getTilePos:function(t){return t.scaleBy(this.getTileSize()).subtract(this._level.origin)},_wrapCoords:function(t){var i=new x(this._wrapX?s(t.x,this._wrapX):t.x,this._wrapY?s(t.y,this._wrapY):t.y);return i.z=t.z,i},_pxBoundsToTileRange:function(t){var i=this.getTileSize();return new P(t.min.unscaleBy(i).floor(),t.max.unscaleBy(i).ceil().subtract([1,1]))},_noTilesToLoad:function(){for(var t in this._tiles)if(!this._tiles[t].loaded)return!1;return!0}}),kn=Sn.extend({options:{minZoom:0,maxZoom:18,subdomains:"abc",errorTileUrl:"",zoomOffset:0,tms:!1,zoomReverse:!1,detectRetina:!1,crossOrigin:!1},initialize:function(t,i){this._url=t,i=l(this,i),i.detectRetina&&ne&&i.maxZoom>0&&(i.tileSize=Math.floor(i.tileSize/2),i.zoomReverse?(i.zoomOffset--,i.minZoom++):(i.zoomOffset++,i.maxZoom--),i.minZoom=Math.max(0,i.minZoom)),"string"==typeof i.subdomains&&(i.subdomains=i.subdomains.split("")),Oi||this.on("tileunload",this._onTileRemove)},setUrl:function(t,i){return this._url=t,i||this.redraw(),this},createTile:function(t,i){var n=document.createElement("img");return V(n,"load",e(this._tileOnLoad,this,i,n)),V(n,"error",e(this._tileOnError,this,i,n)),this.options.crossOrigin&&(n.crossOrigin=""),n.alt="",n.setAttribute("role","presentation"),n.src=this.getTileUrl(t),n},getTileUrl:function(t){var e={r:ne?"@2x":"",s:this._getSubdomain(t),x:t.x,y:t.y,z:this._getZoomForUrl()};if(this._map&&!this._map.options.crs.infinite){var n=this._globalTileRange.max.y-t.y;this.options.tms&&(e.y=n),e["-y"]=n}return _(this._url,i(e,this.options))},_tileOnLoad:function(t,i){Bi?setTimeout(e(t,this,null,i),0):t(null,i)},_tileOnError:function(t,i,e){var n=this.options.errorTileUrl;n&&i.src!==n&&(i.src=n),t(e,i)},_onTileRemove:function(t){t.tile.onload=null},_getZoomForUrl:function(){var t=this._tileZoom,i=this.options.maxZoom,e=this.options.zoomReverse,n=this.options.zoomOffset;return e&&(t=i-t),t+n},_getSubdomain:function(t){var i=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[i]},_abortLoading:function(){var t,i;for(t in this._tiles)this._tiles[t].coords.z!==this._tileZoom&&(i=this._tiles[t].el,i.onload=r,i.onerror=r,i.complete||(i.src=mi,ut(i)))}}),Bn=kn.extend({defaultWmsParams:{service:"WMS",request:"GetMap",layers:"",styles:"",format:"image/jpeg",transparent:!1,version:"1.1.1"},options:{crs:null,uppercase:!1},initialize:function(t,e){this._url=t;var n=i({},this.defaultWmsParams);for(var o in e)o in this.options||(n[o]=e[o]);e=l(this,e),n.width=n.height=e.tileSize*(e.detectRetina&&ne?2:1),this.wmsParams=n},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var i=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[i]=this._crs.code,kn.prototype.onAdd.call(this,t)},getTileUrl:function(t){var i=this._tileCoordsToBounds(t),e=this._crs.project(i.getNorthWest()),n=this._crs.project(i.getSouthEast()),o=(this._wmsVersion>=1.3&&this._crs===nn?[n.y,e.x,e.y,n.x]:[e.x,n.y,n.x,e.y]).join(","),s=kn.prototype.getTileUrl.call(this,t);return s+c(this.wmsParams,s,this.options.uppercase)+(this.options.uppercase?"&BBOX=":"&bbox=")+o},setParams:function(t,e){return i(this.wmsParams,t),e||this.redraw(),this}});kn.WMS=Bn,si.wms=ri;var In=sn.extend({options:{padding:.1},initialize:function(t){l(this,t),n(this),this._layers=this._layers||{}},onAdd:function(){this._container||(this._initContainer(),this._zoomAnimated&&pt(this._container,"leaflet-zoom-animated")),this.getPane().appendChild(this._container),this._update(),this.on("update",this._updatePaths,this)},onRemove:function(){this.off("update",this._updatePaths,this),this._destroyContainer()},getEvents:function(){var t={viewreset:this._reset,zoom:this._onZoom,moveend:this._update,zoomend:this._onZoomEnd};return this._zoomAnimated&&(t.zoomanim=this._onAnimZoom),t},_onAnimZoom:function(t){this._updateTransform(t.center,t.zoom)},_onZoom:function(){this._updateTransform(this._map.getCenter(),this._map.getZoom())},_updateTransform:function(t,i){var e=this._map.getZoomScale(i,this._zoom),n=Pt(this._container),o=this._map.getSize().multiplyBy(.5+this.options.padding),s=this._map.project(this._center,i),r=this._map.project(t,i),a=r.subtract(s),h=o.multiplyBy(-e).add(n).add(o).subtract(a);Ki?wt(this._container,h,e):Lt(this._container,h)},_reset:function(){this._update(),this._updateTransform(this._center,this._zoom);for(var t in this._layers)this._layers[t]._reset()},_onZoomEnd:function(){for(var t in this._layers)this._layers[t]._project()},_updatePaths:function(){for(var t in this._layers)this._layers[t]._update()},_update:function(){var t=this.options.padding,i=this._map.getSize(),e=this._map.containerPointToLayerPoint(i.multiplyBy(-t)).round();this._bounds=new P(e,e.add(i.multiplyBy(1+2*t)).round()),this._center=this._map.getCenter(),this._zoom=this._map.getZoom()}}),An=In.extend({getEvents:function(){var t=In.prototype.getEvents.call(this);return t.viewprereset=this._onViewPreReset,t},_onViewPreReset:function(){this._postponeUpdatePaths=!0},onAdd:function(){In.prototype.onAdd.call(this),this._draw()},_initContainer:function(){var t=this._container=document.createElement("canvas");V(t,"mousemove",o(this._onMouseMove,32,this),this),V(t,"click dblclick mousedown mouseup contextmenu",this._onClick,this),V(t,"mouseout",this._handleMouseOut,this),this._ctx=t.getContext("2d")},_destroyContainer:function(){delete this._ctx,ut(this._container),G(this._container),delete this._container},_updatePaths:function(){if(!this._postponeUpdatePaths){var t;this._redrawBounds=null;for(var i in this._layers)t=this._layers[i],t._update();this._redraw()}},_update:function(){if(!this._map._animatingZoom||!this._bounds){this._drawnLayers={},In.prototype._update.call(this);var t=this._bounds,i=this._container,e=t.getSize(),n=ne?2:1;Lt(i,t.min),i.width=n*e.x,i.height=n*e.y,i.style.width=e.x+"px",i.style.height=e.y+"px",ne&&this._ctx.scale(2,2),this._ctx.translate(-t.min.x,-t.min.y),this.fire("update")}},_reset:function(){In.prototype._reset.call(this),this._postponeUpdatePaths&&(this._postponeUpdatePaths=!1,this._updatePaths())},_initPath:function(t){this._updateDashArray(t),this._layers[n(t)]=t;var i=t._order={layer:t,prev:this._drawLast,next:null};this._drawLast&&(this._drawLast.next=i),this._drawLast=i,this._drawFirst=this._drawFirst||this._drawLast},_addPath:function(t){this._requestRedraw(t)},_removePath:function(t){var i=t._order,e=i.next,n=i.prev;e?e.prev=n:this._drawLast=n,n?n.next=e:this._drawFirst=e,delete t._order,delete this._layers[L.stamp(t)],this._requestRedraw(t)},_updatePath:function(t){this._extendRedrawBounds(t),t._project(),t._update(),this._requestRedraw(t)},_updateStyle:function(t){this._updateDashArray(t),this._requestRedraw(t)},_updateDashArray:function(t){if(t.options.dashArray){var i,e=t.options.dashArray.split(","),n=[];for(i=0;i')}}catch(t){return function(t){return document.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),Rn={_initContainer:function(){this._container=ht("div","leaflet-vml-container")},_update:function(){this._map._animatingZoom||(In.prototype._update.call(this),this.fire("update"))},_initPath:function(t){var i=t._container=On("shape");pt(i,"leaflet-vml-shape "+(this.options.className||"")),i.coordsize="1 1",t._path=On("path"),i.appendChild(t._path),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){var i=t._container;this._container.appendChild(i),t.options.interactive&&t.addInteractiveTarget(i)},_removePath:function(t){var i=t._container;ut(i),t.removeInteractiveTarget(i),delete this._layers[n(t)]},_updateStyle:function(t){var i=t._stroke,e=t._fill,n=t.options,o=t._container;o.stroked=!!n.stroke,o.filled=!!n.fill,n.stroke?(i||(i=t._stroke=On("stroke")),o.appendChild(i),i.weight=n.weight+"px",i.color=n.color,i.opacity=n.opacity,n.dashArray?i.dashStyle=pi(n.dashArray)?n.dashArray.join(" "):n.dashArray.replace(/( *, *)/g," "):i.dashStyle="",i.endcap=n.lineCap.replace("butt","flat"),i.joinstyle=n.lineJoin):i&&(o.removeChild(i),t._stroke=null),n.fill?(e||(e=t._fill=On("fill")),o.appendChild(e),e.color=n.fillColor||n.color,e.opacity=n.fillOpacity):e&&(o.removeChild(e),t._fill=null)},_updateCircle:function(t){var i=t._point.round(),e=Math.round(t._radius),n=Math.round(t._radiusY||e);this._setPath(t,t._empty()?"M0 0":"AL "+i.x+","+i.y+" "+e+","+n+" 0,23592600")},_setPath:function(t,i){t._path.v=i},_bringToFront:function(t){ct(t._container)},_bringToBack:function(t){_t(t._container)}},Dn=re?On:S,Nn=In.extend({getEvents:function(){var t=In.prototype.getEvents.call(this);return t.zoomstart=this._onZoomStart,t},_initContainer:function(){this._container=Dn("svg"),this._container.setAttribute("pointer-events","none"),this._rootGroup=Dn("g"),this._container.appendChild(this._rootGroup)},_destroyContainer:function(){ut(this._container),G(this._container),delete this._container,delete this._rootGroup},_onZoomStart:function(){this._update()},_update:function(){if(!this._map._animatingZoom||!this._bounds){In.prototype._update.call(this);var t=this._bounds,i=t.getSize(),e=this._container;this._svgSize&&this._svgSize.equals(i)||(this._svgSize=i,e.setAttribute("width",i.x),e.setAttribute("height",i.y)),Lt(e,t.min),e.setAttribute("viewBox",[t.min.x,t.min.y,i.x,i.y].join(" ")),this.fire("update")}},_initPath:function(t){var i=t._path=Dn("path");t.options.className&&pt(i,t.options.className),t.options.interactive&&pt(i,"leaflet-interactive"),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){this._rootGroup||this._initContainer(),this._rootGroup.appendChild(t._path),t.addInteractiveTarget(t._path)},_removePath:function(t){ut(t._path),t.removeInteractiveTarget(t._path),delete this._layers[n(t)]},_updatePath:function(t){t._project(),t._update()},_updateStyle:function(t){var i=t._path,e=t.options;i&&(e.stroke?(i.setAttribute("stroke",e.color),i.setAttribute("stroke-opacity",e.opacity),i.setAttribute("stroke-width",e.weight),i.setAttribute("stroke-linecap",e.lineCap),i.setAttribute("stroke-linejoin",e.lineJoin),e.dashArray?i.setAttribute("stroke-dasharray",e.dashArray):i.removeAttribute("stroke-dasharray"),e.dashOffset?i.setAttribute("stroke-dashoffset",e.dashOffset):i.removeAttribute("stroke-dashoffset")):i.setAttribute("stroke","none"),e.fill?(i.setAttribute("fill",e.fillColor||e.color),i.setAttribute("fill-opacity",e.fillOpacity),i.setAttribute("fill-rule",e.fillRule||"evenodd")):i.setAttribute("fill","none"))},_updatePoly:function(t,i){this._setPath(t,k(t._parts,i))},_updateCircle:function(t){var i=t._point,e=t._radius,n=t._radiusY||e,o="a"+e+","+n+" 0 1,0 ",s=t._empty()?"M0 0":"M"+(i.x-e)+","+i.y+o+2*e+",0 "+o+2*-e+",0 ";this._setPath(t,s)},_setPath:function(t,i){t._path.setAttribute("d",i)},_bringToFront:function(t){ct(t._path)},_bringToBack:function(t){_t(t._path)}});re&&Nn.include(Rn),Se.include({getRenderer:function(t){var i=t.options.renderer||this._getPaneRenderer(t.options.pane)||this.options.renderer||this._renderer;return i||(i=this._renderer=this.options.preferCanvas&&ai()||hi()),this.hasLayer(i)||this.addLayer(i),i},_getPaneRenderer:function(t){if("overlayPane"===t||void 0===t)return!1;var i=this._paneRenderers[t];return void 0===i&&(i=Nn&&hi({pane:t})||An&&ai({pane:t}),this._paneRenderers[t]=i),i}});var jn=vn.extend({initialize:function(t,i){vn.prototype.initialize.call(this,this._boundsToLatLngs(t),i)},setBounds:function(t){return this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=z(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}});Nn.create=Dn,Nn.pointsToPath=k,yn.geometryToLayer=Kt,yn.coordsToLatLng=Yt,yn.coordsToLatLngs=Xt,yn.latLngToCoords=Jt,yn.latLngsToCoords=$t,yn.getFeature=Qt,yn.asFeature=ti,Se.mergeOptions({boxZoom:!0});var Wn=Fe.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._resetStateTimeout=0,t.on("unload",this._destroy,this)},addHooks:function(){V(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){G(this._container,"mousedown",this._onMouseDown,this)},moved:function(){return this._moved},_destroy:function(){ut(this._pane),delete this._pane},_resetState:function(){this._resetStateTimeout=0,this._moved=!1},_clearDeferredResetState:function(){0!==this._resetStateTimeout&&(clearTimeout(this._resetStateTimeout),this._resetStateTimeout=0)},_onMouseDown:function(t){return!(!t.shiftKey||1!==t.which&&1!==t.button)&&(this._clearDeferredResetState(),this._resetState(),zi(),bt(),this._startPoint=this._map.mouseEventToContainerPoint(t),void V(document,{contextmenu:Q,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this))},_onMouseMove:function(t){this._moved||(this._moved=!0,this._box=ht("div","leaflet-zoom-box",this._container),pt(this._container,"leaflet-crosshair"),this._map.fire("boxzoomstart")),this._point=this._map.mouseEventToContainerPoint(t);var i=new P(this._point,this._startPoint),e=i.getSize();Lt(this._box,i.min),this._box.style.width=e.x+"px",this._box.style.height=e.y+"px"},_finish:function(){this._moved&&(ut(this._box),mt(this._container,"leaflet-crosshair")),Mi(),Tt(),G(document,{contextmenu:Q,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseUp:function(t){if((1===t.which||1===t.button)&&(this._finish(),this._moved)){this._clearDeferredResetState(),this._resetStateTimeout=setTimeout(e(this._resetState,this),0);var i=new T(this._map.containerPointToLatLng(this._startPoint),this._map.containerPointToLatLng(this._point));this._map.fitBounds(i).fire("boxzoomend",{boxZoomBounds:i})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}});Se.addInitHook("addHandler","boxZoom",Wn),Se.mergeOptions({doubleClickZoom:!0});var Hn=Fe.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var i=this._map,e=i.getZoom(),n=i.options.zoomDelta,o=t.originalEvent.shiftKey?e-n:e+n;"center"===i.options.doubleClickZoom?i.setZoom(o):i.setZoomAround(t.containerPoint,o)}});Se.addInitHook("addHandler","doubleClickZoom",Hn),Se.mergeOptions({dragging:!0,inertia:!Ri,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,easeLinearity:.2,worldCopyJump:!1,maxBoundsViscosity:0});var Fn=Fe.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new Ye(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),this._draggable.on("predrag",this._onPreDragLimit,this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDragWrap,this),t.on("zoomend",this._onZoomEnd,this),t.whenReady(this._onZoomEnd,this))}pt(this._map._container,"leaflet-grab leaflet-touch-drag"),this._draggable.enable(),this._positions=[],this._times=[]},removeHooks:function(){mt(this._map._container,"leaflet-grab"),mt(this._map._container,"leaflet-touch-drag"),this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},moving:function(){return this._draggable&&this._draggable._moving},_onDragStart:function(){var t=this._map;if(t._stop(),this._map.options.maxBounds&&this._map.options.maxBoundsViscosity){var i=z(this._map.options.maxBounds);this._offsetLimit=b(this._map.latLngToContainerPoint(i.getNorthWest()).multiplyBy(-1),this._map.latLngToContainerPoint(i.getSouthEast()).multiplyBy(-1).add(this._map.getSize())),this._viscosity=Math.min(1,Math.max(0,this._map.options.maxBoundsViscosity))}else this._offsetLimit=null;t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(t){if(this._map.options.inertia){var i=this._lastTime=+new Date,e=this._lastPos=this._draggable._absPos||this._draggable._newPos;this._positions.push(e),this._times.push(i),i-this._times[0]>50&&(this._positions.shift(),this._times.shift())}this._map.fire("move",t).fire("drag",t)},_onZoomEnd:function(){var t=this._map.getSize().divideBy(2),i=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=i.subtract(t).x,this._worldWidth=this._map.getPixelWorldBounds().getSize().x},_viscousLimit:function(t,i){return t-(t-i)*this._viscosity},_onPreDragLimit:function(){if(this._viscosity&&this._offsetLimit){var t=this._draggable._newPos.subtract(this._draggable._startPos),i=this._offsetLimit;t.xi.max.x&&(t.x=this._viscousLimit(t.x,i.max.x)),t.y>i.max.y&&(t.y=this._viscousLimit(t.y,i.max.y)),this._draggable._newPos=this._draggable._startPos.add(t)}},_onPreDragWrap:function(){ -var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)0?s:-s))-i;this._delta=0,this._startTime=null,r&&("center"===t.options.scrollWheelZoom?t.setZoom(i+r):t.setZoomAround(this._lastMousePos,i+r))}});Se.addInitHook("addHandler","scrollWheelZoom",Vn),Se.mergeOptions({tap:!0,tapTolerance:15});var Gn=Fe.extend({addHooks:function(){V(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){G(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if($(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new x(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&pt(n,"leaflet-active"),this._holdTimeout=setTimeout(e(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),this._simulateEvent("mousedown",i),V(document,{touchmove:this._onMove,touchend:this._onUp},this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),G(document,{touchmove:this._onMove,touchend:this._onUp},this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],e=i.target;e&&e.tagName&&"a"===e.tagName.toLowerCase()&&mt(e,"leaflet-active"),this._simulateEvent("mouseup",i),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var i=t.touches[0];this._newPos=new x(i.clientX,i.clientY),this._simulateEvent("mousemove",i)},_simulateEvent:function(t,i){var e=document.createEvent("MouseEvents");e._simulated=!0,i.target._simulatedClick=!0,e.initMouseEvent(t,!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),i.target.dispatchEvent(e)}});te&&!Qi&&Se.addInitHook("addHandler","tap",Gn),Se.mergeOptions({touchZoom:te&&!Ri,bounceAtZoomLimits:!0});var qn=Fe.extend({addHooks:function(){pt(this._map._container,"leaflet-touch-zoom"),V(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){mt(this._map._container,"leaflet-touch-zoom"),G(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var e=i.mouseEventToContainerPoint(t.touches[0]),n=i.mouseEventToContainerPoint(t.touches[1]);this._centerPoint=i.getSize()._divideBy(2),this._startLatLng=i.containerPointToLatLng(this._centerPoint),"center"!==i.options.touchZoom&&(this._pinchStartLatLng=i.containerPointToLatLng(e.add(n)._divideBy(2))),this._startDist=e.distanceTo(n),this._startZoom=i.getZoom(),this._moved=!1,this._zooming=!0,i._stop(),V(document,"touchmove",this._onTouchMove,this),V(document,"touchend",this._onTouchEnd,this),$(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length&&this._zooming){var i=this._map,n=i.mouseEventToContainerPoint(t.touches[0]),o=i.mouseEventToContainerPoint(t.touches[1]),s=n.distanceTo(o)/this._startDist;if(this._zoom=i.getScaleZoom(s,this._startZoom),!i.options.bounceAtZoomLimits&&(this._zoomi.getMaxZoom()&&s>1)&&(this._zoom=i._limitZoom(this._zoom)),"center"===i.options.touchZoom){if(this._center=this._startLatLng,1===s)return}else{var r=n._add(o)._divideBy(2)._subtract(this._centerPoint);if(1===s&&0===r.x&&0===r.y)return;this._center=i.unproject(i.project(this._pinchStartLatLng,this._zoom).subtract(r),this._zoom)}this._moved||(i._moveStart(!0),this._moved=!0),g(this._animRequest);var a=e(i._move,i,this._center,this._zoom,{pinch:!0,round:!1});this._animRequest=f(a,this,!0),$(t)}},_onTouchEnd:function(){return this._moved&&this._zooming?(this._zooming=!1,g(this._animRequest),G(document,"touchmove",this._onTouchMove),G(document,"touchend",this._onTouchEnd),void(this._map.options.zoomAnimation?this._map._animateZoom(this._center,this._map._limitZoom(this._zoom),!0,this._map.options.zoomSnap):this._map._resetView(this._center,this._map._limitZoom(this._zoom)))):void(this._zooming=!1)}});Se.addInitHook("addHandler","touchZoom",qn),Se.BoxZoom=Wn,Se.DoubleClickZoom=Hn,Se.Drag=Fn,Se.Keyboard=Un,Se.ScrollWheelZoom=Vn,Se.Tap=Gn,Se.TouchZoom=qn;var Kn=window.L;window.L=t,t.version="1.1.0",t.noConflict=li,t.Control=ke,t.control=Be,t.Browser=ae,t.Evented=wi,t.Mixin=Ue,t.Util=yi,t.Class=v,t.Handler=Fe,t.extend=i,t.bind=e,t.stamp=n,t.setOptions=l,t.DomEvent=Le,t.DomUtil=Ze,t.PosAnimation=Ee,t.Draggable=Ye,t.LineUtil=Xe,t.PolyUtil=Je,t.Point=x,t.point=w,t.Bounds=P,t.bounds=b,t.Transformation=Z,t.transformation=E,t.Projection=tn,t.LatLng=M,t.latLng=C,t.LatLngBounds=T,t.latLngBounds=z,t.CRS=Li,t.GeoJSON=yn,t.geoJSON=ii,t.geoJson=wn,t.Layer=sn,t.LayerGroup=rn,t.layerGroup=an,t.FeatureGroup=hn,t.featureGroup=un,t.ImageOverlay=Ln,t.imageOverlay=Pn,t.VideoOverlay=bn,t.videoOverlay=ei,t.DivOverlay=Tn,t.Popup=zn,t.popup=Mn,t.Tooltip=Cn,t.tooltip=Zn,t.Icon=ln,t.icon=Ht,t.DivIcon=En,t.divIcon=ni,t.Marker=dn,t.marker=Ft,t.TileLayer=kn,t.tileLayer=si,t.GridLayer=Sn,t.gridLayer=oi,t.SVG=Nn,t.svg=hi,t.Renderer=In,t.Canvas=An,t.canvas=ai,t.Path=pn,t.CircleMarker=mn,t.circleMarker=Ut,t.Circle=fn,t.circle=Vt,t.Polyline=gn,t.polyline=Gt,t.Polygon=vn,t.polygon=qt,t.Rectangle=jn,t.rectangle=ui,t.Map=Se,t.map=Ct}) \ No newline at end of file +var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)0?s:-s))-i;this._delta=0,this._startTime=null,r&&("center"===t.options.scrollWheelZoom?t.setZoom(i+r):t.setZoomAround(this._lastMousePos,i+r))}});Se.addInitHook("addHandler","scrollWheelZoom",Vn),Se.mergeOptions({tap:!0,tapTolerance:15});var Gn=Fe.extend({addHooks:function(){V(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){G(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if($(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new x(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&pt(n,"leaflet-active"),this._holdTimeout=setTimeout(e(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),this._simulateEvent("mousedown",i),V(document,{touchmove:this._onMove,touchend:this._onUp},this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),G(document,{touchmove:this._onMove,touchend:this._onUp},this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],e=i.target;e&&e.tagName&&"a"===e.tagName.toLowerCase()&&mt(e,"leaflet-active"),this._simulateEvent("mouseup",i),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var i=t.touches[0];this._newPos=new x(i.clientX,i.clientY),this._simulateEvent("mousemove",i)},_simulateEvent:function(t,i){var e=document.createEvent("MouseEvents");e._simulated=!0,i.target._simulatedClick=!0,e.initMouseEvent(t,!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),i.target.dispatchEvent(e)}});te&&!Qi&&Se.addInitHook("addHandler","tap",Gn),Se.mergeOptions({touchZoom:te&&!Ri,bounceAtZoomLimits:!0});var qn=Fe.extend({addHooks:function(){pt(this._map._container,"leaflet-touch-zoom"),V(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){mt(this._map._container,"leaflet-touch-zoom"),G(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var e=i.mouseEventToContainerPoint(t.touches[0]),n=i.mouseEventToContainerPoint(t.touches[1]);this._centerPoint=i.getSize()._divideBy(2),this._startLatLng=i.containerPointToLatLng(this._centerPoint),"center"!==i.options.touchZoom&&(this._pinchStartLatLng=i.containerPointToLatLng(e.add(n)._divideBy(2))),this._startDist=e.distanceTo(n),this._startZoom=i.getZoom(),this._moved=!1,this._zooming=!0,i._stop(),V(document,"touchmove",this._onTouchMove,this),V(document,"touchend",this._onTouchEnd,this),$(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length&&this._zooming){var i=this._map,n=i.mouseEventToContainerPoint(t.touches[0]),o=i.mouseEventToContainerPoint(t.touches[1]),s=n.distanceTo(o)/this._startDist;if(this._zoom=i.getScaleZoom(s,this._startZoom),!i.options.bounceAtZoomLimits&&(this._zoomi.getMaxZoom()&&s>1)&&(this._zoom=i._limitZoom(this._zoom)),"center"===i.options.touchZoom){if(this._center=this._startLatLng,1===s)return}else{var r=n._add(o)._divideBy(2)._subtract(this._centerPoint);if(1===s&&0===r.x&&0===r.y)return;this._center=i.unproject(i.project(this._pinchStartLatLng,this._zoom).subtract(r),this._zoom)}this._moved||(i._moveStart(!0),this._moved=!0),g(this._animRequest);var a=e(i._move,i,this._center,this._zoom,{pinch:!0,round:!1});this._animRequest=f(a,this,!0),$(t)}},_onTouchEnd:function(){return this._moved&&this._zooming?(this._zooming=!1,g(this._animRequest),G(document,"touchmove",this._onTouchMove),G(document,"touchend",this._onTouchEnd),void(this._map.options.zoomAnimation?this._map._animateZoom(this._center,this._map._limitZoom(this._zoom),!0,this._map.options.zoomSnap):this._map._resetView(this._center,this._map._limitZoom(this._zoom)))):void(this._zooming=!1)}});Se.addInitHook("addHandler","touchZoom",qn),Se.BoxZoom=Wn,Se.DoubleClickZoom=Hn,Se.Drag=Fn,Se.Keyboard=Un,Se.ScrollWheelZoom=Vn,Se.Tap=Gn,Se.TouchZoom=qn;var Kn=window.L;window.L=t,t.version="1.1.0",t.noConflict=li,t.Control=ke,t.control=Be,t.Browser=ae,t.Evented=wi,t.Mixin=Ue,t.Util=yi,t.Class=v,t.Handler=Fe,t.extend=i,t.bind=e,t.stamp=n,t.setOptions=l,t.DomEvent=Le,t.DomUtil=Ze,t.PosAnimation=Ee,t.Draggable=Ye,t.LineUtil=Xe,t.PolyUtil=Je,t.Point=x,t.point=w,t.Bounds=P,t.bounds=b,t.Transformation=Z,t.transformation=E,t.Projection=tn,t.LatLng=M,t.latLng=C,t.LatLngBounds=T,t.latLngBounds=z,t.CRS=Li,t.GeoJSON=yn,t.geoJSON=ii,t.geoJson=wn,t.Layer=sn,t.LayerGroup=rn,t.layerGroup=an,t.FeatureGroup=hn,t.featureGroup=un,t.ImageOverlay=Ln,t.imageOverlay=Pn,t.VideoOverlay=bn,t.videoOverlay=ei,t.DivOverlay=Tn,t.Popup=zn,t.popup=Mn,t.Tooltip=Cn,t.tooltip=Zn,t.Icon=ln,t.icon=Ht,t.DivIcon=En,t.divIcon=ni,t.Marker=dn,t.marker=Ft,t.TileLayer=kn,t.tileLayer=si,t.GridLayer=Sn,t.gridLayer=oi,t.SVG=Nn,t.svg=hi,t.Renderer=In,t.Canvas=An,t.canvas=ai,t.Path=pn,t.CircleMarker=mn,t.circleMarker=Ut,t.Circle=fn,t.circle=Vt,t.Polyline=gn,t.polyline=Gt,t.Polygon=vn,t.polygon=qt,t.Rectangle=jn,t.rectangle=ui,t.Map=Se,t.map=Ct}) \ 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 a5e2b5e4fffcc75f69471635ef30940c2c52c673..ac93508be615c5d062f3bfa51d06e61d0114c23d 100644 GIT binary patch delta 34 rcmcb5lWFNqrVYJoB+5l*AJ`Cih(VX5CgQI8fAOOyf5?a=FfjlCAs7!H delta 82 zcmZ2_lj-VBrVYJoJVZ`~`*6Noy4=Nf(#<{Qhi->$-aA*G#U=Aopnl7~V1sKb9j1L` p)|i;E?%>+Q;MOHf6W2B-TeTJ@74RQWtNv8axX=6ei`fZG3;>TFCm#R+ diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html new file mode 100644 index 00000000000..99d4b1db86e --- /dev/null +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html.gz new file mode 100644 index 0000000000000000000000000000000000000000..f80112f596de006935b9393f102991d2ac6264aa GIT binary patch literal 5303 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 literal 0 HcmV?d00001 diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-zwave.html b/homeassistant/components/frontend/www_static/panels/ha-panel-zwave.html index dd54aa1192f..f4142c54f23 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-zwave.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-zwave.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-zwave.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-zwave.html.gz index 93eae9a0374bdf58940cb490fd95d44f96d29186..271ecd66614574e05e16afc3d92badd497f1a482 100644 GIT binary patch delta 9752 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 delta 9789 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 VlJ-5j;^zLV-y*tg-k0+X3;=L0*<=6! diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index 2a123e7a0ab..62d99bab65c 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=[["/","78ea41075e1cab2bdc72e474bc905291"],["/frontend/panels/dev-event-4886c821235492b1b92739b580d21c61.html","0f16df49a7d965ddc1fd55f7bd3ffd3f"],["/frontend/panels/dev-info-24e888ec7a8acd0c395b34396e9001bc.html","7bb116813e8dbab7bcfabdf4de3ec83f"],["/frontend/panels/dev-service-ac2c50e486927dc4443e93d79f08c06e.html","1daf8c159d2fab036f7094b0e737f1a0"],["/frontend/panels/dev-state-8f1a27c04db6329d31cfcc7d0d6a0869.html","002ea95ab67f5c06f9112008a81e571b"],["/frontend/panels/dev-template-82cd543177c417e5c6612e07df851e6b.html","81c4dbc540739dcf49c351cf565db71b"],["/frontend/panels/map-d3dae1400ec4e4cd7681d2aa79131d55.html","19102e8bcbe3735db7358068b17f323a"],["/static/compatibility-8e4c44b5f4288cc48ec1ba94a9bec812.js","4704a985ad259e324c3d8a0a40f6d937"],["/static/core-d4a7cb8c80c62b536764e0e81385f6aa.js","37e34ec6aa0fa155c7d50e2883be1ead"],["/static/frontend-a7d4cb8260e8094342b5bd8c36c4bf5b.html","73343b5bed6f016b2ba7ff8ee4a1e219"],["/static/mdi-c92bd28c434865d6cabb34cd3c0a3e4c.html","7e24a0584d139fef75d7678ef3c3b008"],["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","32b5a9b7ada86304bec6b43d3f2194f0"]],cacheName="sw-precache-v3--"+(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()},cleanResponse=function(e){return e.redirected?("body"in e?Promise.resolve(e.body):e.blob()).then(function(t){return new Response(t,{headers:e.headers,status:e.status,statusText:e.statusText})}):Promise.resolve(e)},createCacheKey=function(e,t,n,a){var c=new URL(e);return a&&c.pathname.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)){var a=new Request(n,{credentials:"same-origin"});return fetch(a).then(function(t){if(!t.ok)throw new Error("Request for "+n+" returned a response with status "+t.status);return cleanResponse(t).then(function(t){return e.put(n,t)})})}}))})}).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);t||(n=addDirectoryIndex(n,"index.html"),t=urlsToCacheKeys.has(n));!t&&"navigate"===e.request.mode&&isPathWhitelisted(["^((?!(static|api|local|service_worker.js|manifest.json)).)*$"],e.request.url)&&(n=new URL("/",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)&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var n,a;for(n=0;nEMa@F;)xxVLey{oQX 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 delta 2401 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 From 7edf14e55f521f9e187bce1f565f4a2ed1237a5a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 21 Jul 2017 21:38:53 -0700 Subject: [PATCH 064/118] Add Intent component (#8434) * Add intent component * Add intent script component * Add shopping list component * Convert Snips to use intent component * Convert Alexa to use intent component * Lint * Fix Alexa tests * Update snips test * Add intent support to conversation * Add API to view shopping list contents * Lint * Fix demo test * Lint * lint * Remove type from slot schema * Add dependency to conversation * Move intent to be a helper * Fix conversation * Clean up intent helper * Fix Alexa * Snips to use new hass.components * Allow registering intents with conversation at any point in time * Shopping list to register sentences * Add HTTP endpoint to Conversation * Add async action option to intent_script * Update API.ai to use intents * Cleanup Alexa * Shopping list component to register built-in panel * Rename shopping list intent to inlude Hass name --- homeassistant/components/alexa.py | 109 ++++----- homeassistant/components/apiai.py | 103 +++------ homeassistant/components/conversation.py | 211 +++++++++++++----- homeassistant/components/frontend/__init__.py | 3 + homeassistant/components/intent_script.py | 100 +++++++++ homeassistant/components/shopping_list.py | 90 ++++++++ homeassistant/components/snips.py | 104 +++------ homeassistant/helpers/intent.py | 165 ++++++++++++++ tests/common.py | 34 ++- tests/components/test_alexa.py | 17 +- tests/components/test_apiai.py | 50 +++-- tests/components/test_conversation.py | 166 ++++++++++---- tests/components/test_demo.py | 78 ++++--- tests/components/test_intent_script.py | 45 ++++ tests/components/test_shopping_list.py | 61 +++++ tests/components/test_snips.py | 30 +-- 16 files changed, 970 insertions(+), 396 deletions(-) create mode 100644 homeassistant/components/intent_script.py create mode 100644 homeassistant/components/shopping_list.py create mode 100644 homeassistant/helpers/intent.py create mode 100644 tests/components/test_intent_script.py create mode 100644 tests/components/test_shopping_list.py diff --git a/homeassistant/components/alexa.py b/homeassistant/components/alexa.py index 1a3708fb746..c121268f93d 100644 --- a/homeassistant/components/alexa.py +++ b/homeassistant/components/alexa.py @@ -15,8 +15,8 @@ import voluptuous as vol from homeassistant.core import callback from homeassistant.const import HTTP_BAD_REQUEST -from homeassistant.helpers import template, script, config_validation as cv -from homeassistant.components.http import HomeAssistantView +from homeassistant.helpers import intent, template, config_validation as cv +from homeassistant.components import http _LOGGER = logging.getLogger(__name__) @@ -60,6 +60,12 @@ class SpeechType(enum.Enum): ssml = "SSML" +SPEECH_MAPPINGS = { + 'plain': SpeechType.plaintext, + 'ssml': SpeechType.ssml, +} + + class CardType(enum.Enum): """The Alexa card types.""" @@ -69,20 +75,6 @@ class CardType(enum.Enum): CONFIG_SCHEMA = vol.Schema({ DOMAIN: { - CONF_INTENTS: { - cv.string: { - vol.Optional(CONF_ACTION): cv.SCRIPT_SCHEMA, - vol.Optional(CONF_CARD): { - vol.Required(CONF_TYPE): cv.enum(CardType), - vol.Required(CONF_TITLE): cv.template, - vol.Required(CONF_CONTENT): cv.template, - }, - vol.Optional(CONF_SPEECH): { - vol.Required(CONF_TYPE): cv.enum(SpeechType), - vol.Required(CONF_TEXT): cv.template, - } - } - }, CONF_FLASH_BRIEFINGS: { cv.string: vol.All(cv.ensure_list, [{ vol.Required(CONF_UID, default=str(uuid.uuid4())): cv.string, @@ -96,40 +88,27 @@ CONFIG_SCHEMA = vol.Schema({ }, extra=vol.ALLOW_EXTRA) -def setup(hass, config): +@asyncio.coroutine +def async_setup(hass, config): """Activate Alexa component.""" - intents = config[DOMAIN].get(CONF_INTENTS, {}) flash_briefings = config[DOMAIN].get(CONF_FLASH_BRIEFINGS, {}) - hass.http.register_view(AlexaIntentsView(hass, intents)) + hass.http.register_view(AlexaIntentsView) hass.http.register_view(AlexaFlashBriefingView(hass, flash_briefings)) return True -class AlexaIntentsView(HomeAssistantView): +class AlexaIntentsView(http.HomeAssistantView): """Handle Alexa requests.""" url = INTENTS_API_ENDPOINT name = 'api:alexa' - def __init__(self, hass, intents): - """Initialize Alexa view.""" - super().__init__() - - intents = copy.deepcopy(intents) - template.attach(hass, intents) - - for name, intent in intents.items(): - if CONF_ACTION in intent: - intent[CONF_ACTION] = script.Script( - hass, intent[CONF_ACTION], "Alexa intent {}".format(name)) - - self.intents = intents - @asyncio.coroutine def post(self, request): """Handle Alexa.""" + hass = request.app['hass'] data = yield from request.json() _LOGGER.debug('Received Alexa request: %s', data) @@ -146,14 +125,14 @@ class AlexaIntentsView(HomeAssistantView): if req_type == 'SessionEndedRequest': return None - intent = req.get('intent') - response = AlexaResponse(request.app['hass'], intent) + alexa_intent_info = req.get('intent') + alexa_response = AlexaResponse(hass, alexa_intent_info) if req_type == 'LaunchRequest': - response.add_speech( + alexa_response.add_speech( SpeechType.plaintext, "Hello, and welcome to the future. How may I help?") - return self.json(response) + return self.json(alexa_response) if req_type != 'IntentRequest': _LOGGER.warning('Received unsupported request: %s', req_type) @@ -161,38 +140,47 @@ class AlexaIntentsView(HomeAssistantView): 'Received unsupported request: {}'.format(req_type), HTTP_BAD_REQUEST) - intent_name = intent['name'] - config = self.intents.get(intent_name) + intent_name = alexa_intent_info['name'] - if config is None: + try: + intent_response = yield from intent.async_handle( + hass, DOMAIN, intent_name, + {key: {'value': value} for key, value + in alexa_response.variables.items()}) + except intent.UnknownIntent as err: _LOGGER.warning('Received unknown intent %s', intent_name) - response.add_speech( + alexa_response.add_speech( SpeechType.plaintext, "This intent is not yet configured within Home Assistant.") - return self.json(response) + return self.json(alexa_response) - speech = config.get(CONF_SPEECH) - card = config.get(CONF_CARD) - action = config.get(CONF_ACTION) + except intent.InvalidSlotInfo as err: + _LOGGER.error('Received invalid slot data from Alexa: %s', err) + return self.json_message('Invalid slot data received', + HTTP_BAD_REQUEST) + except intent.IntentError: + _LOGGER.exception('Error handling request for %s', intent_name) + return self.json_message('Error handling intent', HTTP_BAD_REQUEST) - if action is not None: - yield from action.async_run(response.variables) + for intent_speech, alexa_speech in SPEECH_MAPPINGS.items(): + if intent_speech in intent_response.speech: + alexa_response.add_speech( + alexa_speech, + intent_response.speech[intent_speech]['speech']) + break - # pylint: disable=unsubscriptable-object - if speech is not None: - response.add_speech(speech[CONF_TYPE], speech[CONF_TEXT]) + if 'simple' in intent_response.card: + alexa_response.add_card( + 'simple', intent_response.card['simple']['title'], + intent_response.card['simple']['content']) - if card is not None: - response.add_card(card[CONF_TYPE], card[CONF_TITLE], - card[CONF_CONTENT]) - - return self.json(response) + return self.json(alexa_response) class AlexaResponse(object): """Help generating the response for Alexa.""" - def __init__(self, hass, intent=None): + def __init__(self, hass, intent_info): """Initialize the response.""" self.hass = hass self.speech = None @@ -201,8 +189,9 @@ class AlexaResponse(object): self.session_attributes = {} self.should_end_session = True self.variables = {} - if intent is not None and 'slots' in intent: - for key, value in intent['slots'].items(): + # Intent is None if request was a LaunchRequest or SessionEndedRequest + if intent_info is not None: + for key, value in intent_info.get('slots', {}).items(): if 'value' in value: underscored_key = key.replace('.', '_') self.variables[underscored_key] = value['value'] @@ -272,7 +261,7 @@ class AlexaResponse(object): } -class AlexaFlashBriefingView(HomeAssistantView): +class AlexaFlashBriefingView(http.HomeAssistantView): """Handle Alexa Flash Briefing skill requests.""" url = FLASH_BRIEFINGS_API_ENDPOINT diff --git a/homeassistant/components/apiai.py b/homeassistant/components/apiai.py index 989c1a596f3..eb6cd0027f7 100644 --- a/homeassistant/components/apiai.py +++ b/homeassistant/components/apiai.py @@ -5,13 +5,12 @@ For more details about this component, please refer to the documentation at https://home-assistant.io/components/apiai/ """ import asyncio -import copy import logging import voluptuous as vol from homeassistant.const import PROJECT_NAME, HTTP_BAD_REQUEST -from homeassistant.helpers import template, script, config_validation as cv +from homeassistant.helpers import intent, template from homeassistant.components.http import HomeAssistantView _LOGGER = logging.getLogger(__name__) @@ -29,24 +28,14 @@ DOMAIN = 'apiai' DEPENDENCIES = ['http'] CONFIG_SCHEMA = vol.Schema({ - DOMAIN: { - CONF_INTENTS: { - cv.string: { - vol.Optional(CONF_SPEECH): cv.template, - vol.Optional(CONF_ACTION): cv.SCRIPT_SCHEMA, - vol.Optional(CONF_ASYNC_ACTION, - default=DEFAULT_CONF_ASYNC_ACTION): cv.boolean - } - } - } + DOMAIN: {} }, extra=vol.ALLOW_EXTRA) -def setup(hass, config): +@asyncio.coroutine +def async_setup(hass, config): """Activate API.AI component.""" - intents = config[DOMAIN].get(CONF_INTENTS, {}) - - hass.http.register_view(ApiaiIntentsView(hass, intents)) + hass.http.register_view(ApiaiIntentsView) return True @@ -57,24 +46,10 @@ class ApiaiIntentsView(HomeAssistantView): url = INTENTS_API_ENDPOINT name = 'api:apiai' - def __init__(self, hass, intents): - """Initialize API.AI view.""" - super().__init__() - - self.hass = hass - intents = copy.deepcopy(intents) - template.attach(hass, intents) - - for name, intent in intents.items(): - if CONF_ACTION in intent: - intent[CONF_ACTION] = script.Script( - hass, intent[CONF_ACTION], "Apiai intent {}".format(name)) - - self.intents = intents - @asyncio.coroutine def post(self, request): """Handle API.AI.""" + hass = request.app['hass'] data = yield from request.json() _LOGGER.debug("Received api.ai request: %s", data) @@ -91,55 +66,41 @@ class ApiaiIntentsView(HomeAssistantView): if action_incomplete: return None - # use intent to no mix HASS actions with this parameter - intent = req.get('action') + action = req.get('action') parameters = req.get('parameters') - # contexts = req.get('contexts') - response = ApiaiResponse(parameters) + apiai_response = ApiaiResponse(parameters) - # Default Welcome Intent - # Maybe is better to handle this in api.ai directly? - # - # if intent == 'input.welcome': - # response.add_speech( - # "Hello, and welcome to the future. How may I help?") - # return self.json(response) - - if intent == "": + if action == "": _LOGGER.warning("Received intent with empty action") - response.add_speech( + apiai_response.add_speech( "You have not defined an action in your api.ai intent.") - return self.json(response) + return self.json(apiai_response) - config = self.intents.get(intent) + try: + intent_response = yield from intent.async_handle( + hass, DOMAIN, action, + {key: {'value': value} for key, value + in parameters.items()}) - if config is None: - _LOGGER.warning("Received unknown intent %s", intent) - response.add_speech( - "Intent '%s' is not yet configured within Home Assistant." % - intent) - return self.json(response) + except intent.UnknownIntent as err: + _LOGGER.warning('Received unknown intent %s', action) + apiai_response.add_speech( + "This intent is not yet configured within Home Assistant.") + return self.json(apiai_response) - speech = config.get(CONF_SPEECH) - action = config.get(CONF_ACTION) - async_action = config.get(CONF_ASYNC_ACTION) + except intent.InvalidSlotInfo as err: + _LOGGER.error('Received invalid slot data: %s', err) + return self.json_message('Invalid slot data received', + HTTP_BAD_REQUEST) + except intent.IntentError: + _LOGGER.exception('Error handling request for %s', action) + return self.json_message('Error handling intent', HTTP_BAD_REQUEST) - if action is not None: - # API.AI expects a response in less than 5s - if async_action: - # Do not wait for the action to be executed. - # Needed if the action will take longer than 5s to execute - self.hass.async_add_job(action.async_run(response.parameters)) - else: - # Wait for the action to be executed so we can use results to - # render the answer - yield from action.async_run(response.parameters) + if 'plain' in intent_response.speech: + apiai_response.add_speech( + intent_response.speech['plain']['speech']) - # pylint: disable=unsubscriptable-object - if speech is not None: - response.add_speech(speech) - - return self.json(response) + return self.json(apiai_response) class ApiaiResponse(object): diff --git a/homeassistant/components/conversation.py b/homeassistant/components/conversation.py index 591190383a0..b682b318c7b 100644 --- a/homeassistant/components/conversation.py +++ b/homeassistant/components/conversation.py @@ -4,6 +4,7 @@ Support for functionality to have conversations with Home Assistant. For more details about this component, please refer to the documentation at https://home-assistant.io/components/conversation/ """ +import asyncio import logging import re import warnings @@ -11,16 +12,17 @@ import warnings import voluptuous as vol from homeassistant import core +from homeassistant.loader import bind_hass from homeassistant.const import ( - ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON) -import homeassistant.helpers.config_validation as cv -from homeassistant.helpers import script + ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, HTTP_BAD_REQUEST) +from homeassistant.helpers import intent, config_validation as cv +from homeassistant.components import http REQUIREMENTS = ['fuzzywuzzy==0.15.0'] +DEPENDENCIES = ['http'] ATTR_TEXT = 'text' -ATTR_SENTENCE = 'sentence' DOMAIN = 'conversation' REGEX_TURN_COMMAND = re.compile(r'turn (?P(?: |\w)+) (?P\w+)') @@ -28,79 +30,168 @@ REGEX_TURN_COMMAND = re.compile(r'turn (?P(?: |\w)+) (?P\w+)') SERVICE_PROCESS = 'process' SERVICE_PROCESS_SCHEMA = vol.Schema({ - vol.Required(ATTR_TEXT): vol.All(cv.string, vol.Lower), + vol.Required(ATTR_TEXT): cv.string, }) CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({ - cv.string: vol.Schema({ - vol.Required(ATTR_SENTENCE): cv.string, - vol.Required('action'): cv.SCRIPT_SCHEMA, + vol.Optional('intents'): vol.Schema({ + cv.string: vol.All(cv.ensure_list, [cv.string]) }) })}, extra=vol.ALLOW_EXTRA) +_LOGGER = logging.getLogger(__name__) -def setup(hass, config): + +@core.callback +@bind_hass +def async_register(hass, intent_type, utterances): + """Register an intent. + + Registrations don't require conversations to be loaded. They will become + active once the conversation component is loaded. + """ + intents = hass.data.get(DOMAIN) + + if intents is None: + intents = hass.data[DOMAIN] = {} + + conf = intents.get(intent_type) + + if conf is None: + conf = intents[intent_type] = [] + + conf.extend(_create_matcher(utterance) for utterance in utterances) + + +@asyncio.coroutine +def async_setup(hass, config): """Register the process service.""" warnings.filterwarnings('ignore', module='fuzzywuzzy') - from fuzzywuzzy import process as fuzzyExtract - logger = logging.getLogger(__name__) config = config.get(DOMAIN, {}) + intents = hass.data.get(DOMAIN) - choices = {attrs[ATTR_SENTENCE]: script.Script( - hass, - attrs['action'], - name) - for name, attrs in config.items()} + if intents is None: + intents = hass.data[DOMAIN] = {} + for intent_type, utterances in config.get('intents', {}).items(): + conf = intents.get(intent_type) + + if conf is None: + conf = intents[intent_type] = [] + + conf.extend(_create_matcher(utterance) for utterance in utterances) + + @asyncio.coroutine def process(service): """Parse text into commands.""" - # if actually configured - if choices: - text = service.data[ATTR_TEXT] - match = fuzzyExtract.extractOne(text, choices.keys()) - scorelimit = 60 # arbitrary value - logging.info( - 'matched up text %s and found %s', - text, - [match[0] if match[1] > scorelimit else 'nothing'] - ) - if match[1] > scorelimit: - choices[match[0]].run() # run respective script - return - text = service.data[ATTR_TEXT] - match = REGEX_TURN_COMMAND.match(text) + yield from _process(hass, text) - if not match: - logger.error("Unable to process: %s", text) - return - - name, command = match.groups() - entities = {state.entity_id: state.name for state in hass.states.all()} - entity_ids = fuzzyExtract.extractOne( - name, entities, score_cutoff=65)[2] - - if not entity_ids: - logger.error( - "Could not find entity id %s from text %s", name, text) - return - - if command == 'on': - hass.services.call(core.DOMAIN, SERVICE_TURN_ON, { - ATTR_ENTITY_ID: entity_ids, - }, blocking=True) - - elif command == 'off': - hass.services.call(core.DOMAIN, SERVICE_TURN_OFF, { - ATTR_ENTITY_ID: entity_ids, - }, blocking=True) - - else: - logger.error('Got unsupported command %s from text %s', - command, text) - - hass.services.register( + hass.services.async_register( DOMAIN, SERVICE_PROCESS, process, schema=SERVICE_PROCESS_SCHEMA) + hass.http.register_view(ConversationProcessView) + return True + + +def _create_matcher(utterance): + """Create a regex that matches the utterance.""" + parts = re.split(r'({\w+})', utterance) + group_matcher = re.compile(r'{(\w+)}') + + pattern = ['^'] + + for part in parts: + match = group_matcher.match(part) + + if match is None: + pattern.append(part) + continue + + pattern.append('(?P<{}>{})'.format(match.groups()[0], r'[\w ]+')) + + pattern.append('$') + return re.compile(''.join(pattern), re.I) + + +@asyncio.coroutine +def _process(hass, text): + """Process a line of text.""" + intents = hass.data.get(DOMAIN, {}) + + for intent_type, matchers in intents.items(): + for matcher in matchers: + match = matcher.match(text) + + if not match: + continue + + response = yield from intent.async_handle( + hass, DOMAIN, intent_type, + {key: {'value': value} for key, value + in match.groupdict().items()}, text) + return response + + from fuzzywuzzy import process as fuzzyExtract + text = text.lower() + match = REGEX_TURN_COMMAND.match(text) + + if not match: + _LOGGER.error("Unable to process: %s", text) + return None + + name, command = match.groups() + entities = {state.entity_id: state.name for state + in hass.states.async_all()} + entity_ids = fuzzyExtract.extractOne( + name, entities, score_cutoff=65)[2] + + if not entity_ids: + _LOGGER.error( + "Could not find entity id %s from text %s", name, text) + return + + if command == 'on': + yield from hass.services.async_call( + core.DOMAIN, SERVICE_TURN_ON, { + ATTR_ENTITY_ID: entity_ids, + }, blocking=True) + + elif command == 'off': + yield from hass.services.async_call( + core.DOMAIN, SERVICE_TURN_OFF, { + ATTR_ENTITY_ID: entity_ids, + }, blocking=True) + + else: + _LOGGER.error('Got unsupported command %s from text %s', + command, text) + + +class ConversationProcessView(http.HomeAssistantView): + """View to retrieve shopping list content.""" + + url = '/api/conversation/process' + name = "api:conversation:process" + + @asyncio.coroutine + def post(self, request): + """Send a request for processing.""" + hass = request.app['hass'] + try: + data = yield from request.json() + except ValueError: + return self.json_message('Invalid JSON specified', + HTTP_BAD_REQUEST) + + text = data.get('text') + + if text is None: + return self.json_message('Missing "text" key in JSON.', + HTTP_BAD_REQUEST) + + intent_result = yield from _process(hass, text) + + return self.json(intent_result) diff --git a/homeassistant/components/frontend/__init__.py b/homeassistant/components/frontend/__init__.py index 443ff6f3852..2674eb062a8 100644 --- a/homeassistant/components/frontend/__init__.py +++ b/homeassistant/components/frontend/__init__.py @@ -12,6 +12,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.config import find_config_file, load_yaml_config_file from homeassistant.const import CONF_NAME, EVENT_THEMES_UPDATED from homeassistant.core import callback +from homeassistant.loader import bind_hass from homeassistant.components import api from homeassistant.components.http import HomeAssistantView from homeassistant.components.http.auth import is_trusted_ip @@ -75,6 +76,7 @@ SERVICE_SET_THEME_SCHEMA = vol.Schema({ }) +@bind_hass def register_built_in_panel(hass, component_name, sidebar_title=None, sidebar_icon=None, url_path=None, config=None): """Register a built-in panel.""" @@ -96,6 +98,7 @@ def register_built_in_panel(hass, component_name, sidebar_title=None, sidebar_icon, url_path, url, config) +@bind_hass def register_panel(hass, component_name, path, md5=None, sidebar_title=None, sidebar_icon=None, url_path=None, url=None, config=None): """Register a panel for the frontend. diff --git a/homeassistant/components/intent_script.py b/homeassistant/components/intent_script.py new file mode 100644 index 00000000000..91489e188c5 --- /dev/null +++ b/homeassistant/components/intent_script.py @@ -0,0 +1,100 @@ +"""Handle intents with scripts.""" +import asyncio +import copy +import logging + +import voluptuous as vol + +from homeassistant.helpers import ( + intent, template, script, config_validation as cv) + +DOMAIN = 'intent_script' + +CONF_INTENTS = 'intents' +CONF_SPEECH = 'speech' + +CONF_ACTION = 'action' +CONF_CARD = 'card' +CONF_TYPE = 'type' +CONF_TITLE = 'title' +CONF_CONTENT = 'content' +CONF_TEXT = 'text' +CONF_ASYNC_ACTION = 'async_action' + +DEFAULT_CONF_ASYNC_ACTION = False + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: { + cv.string: { + vol.Optional(CONF_ACTION): cv.SCRIPT_SCHEMA, + vol.Optional(CONF_ASYNC_ACTION, + default=DEFAULT_CONF_ASYNC_ACTION): cv.boolean, + vol.Optional(CONF_CARD): { + vol.Optional(CONF_TYPE, default='simple'): cv.string, + vol.Required(CONF_TITLE): cv.template, + vol.Required(CONF_CONTENT): cv.template, + }, + vol.Optional(CONF_SPEECH): { + vol.Optional(CONF_TYPE, default='plain'): cv.string, + vol.Required(CONF_TEXT): cv.template, + } + } + } +}, extra=vol.ALLOW_EXTRA) + +_LOGGER = logging.getLogger(__name__) + + +@asyncio.coroutine +def async_setup(hass, config): + """Activate Alexa component.""" + intents = copy.deepcopy(config[DOMAIN]) + template.attach(hass, intents) + + for intent_type, conf in intents.items(): + if CONF_ACTION in conf: + conf[CONF_ACTION] = script.Script( + hass, conf[CONF_ACTION], + "Intent Script {}".format(intent_type)) + intent.async_register(hass, ScriptIntentHandler(intent_type, conf)) + + return True + + +class ScriptIntentHandler(intent.IntentHandler): + """Respond to an intent with a script.""" + + def __init__(self, intent_type, config): + """Initialize the script intent handler.""" + self.intent_type = intent_type + self.config = config + + @asyncio.coroutine + def async_handle(self, intent_obj): + """Handle the intent.""" + speech = self.config.get(CONF_SPEECH) + card = self.config.get(CONF_CARD) + action = self.config.get(CONF_ACTION) + is_async_action = self.config.get(CONF_ASYNC_ACTION) + slots = {key: value['value'] for key, value + in intent_obj.slots.items()} + + if action is not None: + if is_async_action: + intent_obj.hass.async_add_job(action.async_run(slots)) + else: + yield from action.async_run(slots) + + response = intent_obj.create_response() + + if speech is not None: + response.async_set_speech(speech[CONF_TEXT].async_render(slots), + speech[CONF_TYPE]) + + if card is not None: + response.async_set_card( + card[CONF_TITLE].async_render(slots), + card[CONF_CONTENT].async_render(slots), + card[CONF_TYPE]) + + return response diff --git a/homeassistant/components/shopping_list.py b/homeassistant/components/shopping_list.py new file mode 100644 index 00000000000..7247579fa39 --- /dev/null +++ b/homeassistant/components/shopping_list.py @@ -0,0 +1,90 @@ +"""Component to manage a shoppling list.""" +import asyncio +import logging + +import voluptuous as vol + +from homeassistant.core import callback +from homeassistant.components import http +from homeassistant.helpers import intent +import homeassistant.helpers.config_validation as cv + + +DOMAIN = 'shopping_list' +DEPENDENCIES = ['http'] +_LOGGER = logging.getLogger(__name__) +CONFIG_SCHEMA = vol.Schema({DOMAIN: {}}, extra=vol.ALLOW_EXTRA) +EVENT = 'shopping_list_updated' +INTENT_ADD_ITEM = 'HassShoppingListAddItem' +INTENT_LAST_ITEMS = 'HassShoppingListLastItems' + + +@asyncio.coroutine +def async_setup(hass, config): + """Initialize the shopping list.""" + hass.data[DOMAIN] = [] + intent.async_register(hass, AddItemIntent()) + intent.async_register(hass, ListTopItemsIntent()) + hass.http.register_view(ShoppingListView) + hass.components.conversation.async_register(INTENT_ADD_ITEM, [ + 'Add {item} to my shopping list', + ]) + hass.components.conversation.async_register(INTENT_LAST_ITEMS, [ + 'What is on my shopping list' + ]) + hass.components.frontend.register_built_in_panel( + 'shopping-list', 'Shopping List', 'mdi:cart') + return True + + +class AddItemIntent(intent.IntentHandler): + """Handle AddItem intents.""" + + intent_type = INTENT_ADD_ITEM + slot_schema = { + 'item': cv.string + } + + @asyncio.coroutine + def async_handle(self, intent_obj): + """Handle the intent.""" + slots = self.async_validate_slots(intent_obj.slots) + item = slots['item']['value'] + intent_obj.hass.data[DOMAIN].append(item) + + response = intent_obj.create_response() + response.async_set_speech( + "I've added {} to your shopping list".format(item)) + intent_obj.hass.bus.async_fire(EVENT) + return response + + +class ListTopItemsIntent(intent.IntentHandler): + """Handle AddItem intents.""" + + intent_type = INTENT_LAST_ITEMS + slot_schema = { + 'item': cv.string + } + + @asyncio.coroutine + def async_handle(self, intent_obj): + """Handle the intent.""" + response = intent_obj.create_response() + response.async_set_speech( + "These are the top 5 items in your shopping list: {}".format( + ', '.join(reversed(intent_obj.hass.data[DOMAIN][-5:])))) + intent_obj.hass.bus.async_fire(EVENT) + return response + + +class ShoppingListView(http.HomeAssistantView): + """View to retrieve shopping list content.""" + + url = '/api/shopping_list' + name = "api:shopping_list" + + @callback + def get(self, request): + """Retrieve if API is running.""" + return self.json(request.app['hass'].data[DOMAIN]) diff --git a/homeassistant/components/snips.py b/homeassistant/components/snips.py index b123de48158..6243de0b2d6 100644 --- a/homeassistant/components/snips.py +++ b/homeassistant/components/snips.py @@ -5,12 +5,10 @@ For more details about this component, please refer to the documentation at https://home-assistant.io/components/snips/ """ import asyncio -import copy import json import logging import voluptuous as vol -from homeassistant.helpers import template, script, config_validation as cv -import homeassistant.loader as loader +from homeassistant.helpers import intent, config_validation as cv DOMAIN = 'snips' DEPENDENCIES = ['mqtt'] @@ -19,16 +17,10 @@ CONF_ACTION = 'action' INTENT_TOPIC = 'hermes/nlu/intentParsed' -LOGGER = logging.getLogger(__name__) +_LOGGER = logging.getLogger(__name__) CONFIG_SCHEMA = vol.Schema({ - DOMAIN: { - CONF_INTENTS: { - cv.string: { - vol.Optional(CONF_ACTION): cv.SCRIPT_SCHEMA, - } - } - } + DOMAIN: {} }, extra=vol.ALLOW_EXTRA) INTENT_SCHEMA = vol.Schema({ @@ -49,74 +41,34 @@ INTENT_SCHEMA = vol.Schema({ @asyncio.coroutine def async_setup(hass, config): """Activate Snips component.""" - mqtt = loader.get_component('mqtt') - intents = config[DOMAIN].get(CONF_INTENTS, {}) - handler = IntentHandler(hass, intents) - @asyncio.coroutine def message_received(topic, payload, qos): """Handle new messages on MQTT.""" - LOGGER.debug("New intent: %s", payload) - yield from handler.handle_intent(payload) + _LOGGER.debug("New intent: %s", payload) - yield from mqtt.async_subscribe(hass, INTENT_TOPIC, message_received) + try: + request = json.loads(payload) + except TypeError: + _LOGGER.error('Received invalid JSON: %s', payload) + return + + try: + request = INTENT_SCHEMA(request) + except vol.Invalid as err: + _LOGGER.error('Intent has invalid schema: %s. %s', err, request) + return + + intent_type = request['intent']['intentName'].split('__')[-1] + slots = {slot['slotName']: {'value': slot['value']['value']} + for slot in request.get('slots', [])} + + try: + yield from intent.async_handle( + hass, DOMAIN, intent_type, slots, request['input']) + except intent.IntentError: + _LOGGER.exception("Error while handling intent.") + + yield from hass.components.mqtt.async_subscribe( + INTENT_TOPIC, message_received) return True - - -class IntentHandler(object): - """Help handling intents.""" - - def __init__(self, hass, intents): - """Initialize the intent handler.""" - self.hass = hass - intents = copy.deepcopy(intents) - template.attach(hass, intents) - - for name, intent in intents.items(): - if CONF_ACTION in intent: - intent[CONF_ACTION] = script.Script( - hass, intent[CONF_ACTION], "Snips intent {}".format(name)) - - self.intents = intents - - @asyncio.coroutine - def handle_intent(self, payload): - """Handle an intent.""" - try: - response = json.loads(payload) - except TypeError: - LOGGER.error('Received invalid JSON: %s', payload) - return - - try: - response = INTENT_SCHEMA(response) - except vol.Invalid as err: - LOGGER.error('Intent has invalid schema: %s. %s', err, response) - return - - intent = response['intent']['intentName'].split('__')[-1] - config = self.intents.get(intent) - - if config is None: - LOGGER.warning("Received unknown intent %s. %s", intent, response) - return - - action = config.get(CONF_ACTION) - - if action is not None: - slots = self.parse_slots(response) - yield from action.async_run(slots) - - # pylint: disable=no-self-use - def parse_slots(self, response): - """Parse the intent slots.""" - parameters = {} - - for slot in response.get('slots', []): - key = slot['slotName'] - value = slot['value']['value'] - if value is not None: - parameters[key] = value - - return parameters diff --git a/homeassistant/helpers/intent.py b/homeassistant/helpers/intent.py new file mode 100644 index 00000000000..459d89a83ce --- /dev/null +++ b/homeassistant/helpers/intent.py @@ -0,0 +1,165 @@ +"""Module to coordinate user intentions.""" +import asyncio +import logging + +import voluptuous as vol + +from homeassistant.core import callback +from homeassistant.exceptions import HomeAssistantError + + +DATA_KEY = 'intent' +_LOGGER = logging.getLogger(__name__) + +SLOT_SCHEMA = vol.Schema({ +}, extra=vol.ALLOW_EXTRA) + +SPEECH_TYPE_PLAIN = 'plain' +SPEECH_TYPE_SSML = 'ssml' + + +@callback +def async_register(hass, handler): + """Register an intent with Home Assistant.""" + intents = hass.data.get(DATA_KEY) + if intents is None: + intents = hass.data[DATA_KEY] = {} + + if handler.intent_type in intents: + _LOGGER.warning('Intent %s is being overwritten by %s.', + handler.intent_type, handler) + + intents[handler.intent_type] = handler + + +@asyncio.coroutine +def async_handle(hass, platform, intent_type, slots=None, text_input=None): + """Handle an intent.""" + handler = hass.data.get(DATA_KEY, {}).get(intent_type) + + if handler is None: + raise UnknownIntent() + + intent = Intent(hass, platform, intent_type, slots or {}, text_input) + + try: + _LOGGER.info("Triggering intent handler %s", handler) + result = yield from handler.async_handle(intent) + return result + except vol.Invalid as err: + raise InvalidSlotInfo from err + except Exception as err: + raise IntentHandleError from err + + +class IntentError(HomeAssistantError): + """Base class for intent related errors.""" + + pass + + +class UnknownIntent(IntentError): + """When the intent is not registered.""" + + pass + + +class InvalidSlotInfo(IntentError): + """When the slot data is invalid.""" + + pass + + +class IntentHandleError(IntentError): + """Error while handling intent.""" + + pass + + +class IntentHandler: + """Intent handler registration.""" + + intent_type = None + slot_schema = None + _slot_schema = None + platforms = None + + @callback + def async_can_handle(self, intent_obj): + """Test if an intent can be handled.""" + return self.platforms is None or intent_obj.platform in self.platforms + + @callback + def async_validate_slots(self, slots): + """Validate slot information.""" + if self.slot_schema is None: + return slots + + if self._slot_schema is None: + self._slot_schema = vol.Schema({ + key: SLOT_SCHEMA.extend({'value': validator}) + for key, validator in self.slot_schema.items()}) + + return self._slot_schema(slots) + + @asyncio.coroutine + def async_handle(self, intent_obj): + """Handle the intent.""" + raise NotImplementedError() + + def __repr__(self): + """String representation of intent handler.""" + return '<{} - {}>'.format(self.__class__.__name__, self.intent_type) + + +class Intent: + """Hold the intent.""" + + __slots__ = ['hass', 'platform', 'intent_type', 'slots', 'text_input'] + + def __init__(self, hass, platform, intent_type, slots, text_input): + """Initialize an intent.""" + self.hass = hass + self.platform = platform + self.intent_type = intent_type + self.slots = slots + self.text_input = text_input + + @callback + def create_response(self): + """Create a response.""" + return IntentResponse(self) + + +class IntentResponse: + """Response to an intent.""" + + def __init__(self, intent): + """Initialize an IntentResponse.""" + self.intent = intent + self.speech = {} + self.card = {} + + @callback + def async_set_speech(self, speech, speech_type='plain', extra_data=None): + """Set speech response.""" + self.speech[speech_type] = { + 'speech': speech, + 'extra_data': extra_data, + } + + @callback + def async_set_card(self, title, content, card_type='simple'): + """Set speech response.""" + self.card[card_type] = { + 'title': title, + 'content': content, + } + + @callback + def as_dict(self): + """Return a dictionary representation of an intent response.""" + return { + 'speech': self.speech, + 'card': self.card, + } diff --git a/tests/common.py b/tests/common.py index b2001a3c837..5e328959a7a 100644 --- a/tests/common.py +++ b/tests/common.py @@ -14,9 +14,7 @@ from aiohttp import web from homeassistant import core as ha, loader from homeassistant.setup import setup_component, async_setup_component from homeassistant.config import async_process_component_config -from homeassistant.helpers.dispatcher import async_dispatcher_send -from homeassistant.helpers.entity import ToggleEntity -from homeassistant.helpers.restore_state import DATA_RESTORE_CACHE +from homeassistant.helpers import intent, dispatcher, entity, restore_state from homeassistant.util.unit_system import METRIC_SYSTEM import homeassistant.util.dt as date_util import homeassistant.util.yaml as yaml @@ -193,12 +191,31 @@ def async_mock_service(hass, domain, service): mock_service = threadsafe_callback_factory(async_mock_service) +@ha.callback +def async_mock_intent(hass, intent_typ): + """Set up a fake intent handler.""" + intents = [] + + class MockIntentHandler(intent.IntentHandler): + intent_type = intent_typ + + @asyncio.coroutine + def async_handle(self, intent): + """Handle the intent.""" + intents.append(intent) + return intent.create_response() + + intent.async_register(hass, MockIntentHandler()) + + return intents + + @ha.callback def async_fire_mqtt_message(hass, topic, payload, qos=0): """Fire the MQTT message.""" if isinstance(payload, str): payload = payload.encode('utf-8') - async_dispatcher_send( + dispatcher.async_dispatcher_send( hass, mqtt.SIGNAL_MQTT_MESSAGE_RECEIVED, topic, payload, qos) @@ -352,7 +369,7 @@ class MockPlatform(object): self._setup_platform(hass, config, add_devices, discovery_info) -class MockToggleDevice(ToggleEntity): +class MockToggleDevice(entity.ToggleEntity): """Provide a mock toggle device.""" def __init__(self, name, state): @@ -506,10 +523,11 @@ def init_recorder_component(hass, add_config=None): def mock_restore_cache(hass, states): """Mock the DATA_RESTORE_CACHE.""" - hass.data[DATA_RESTORE_CACHE] = { + key = restore_state.DATA_RESTORE_CACHE + hass.data[key] = { state.entity_id: state for state in states} - _LOGGER.debug('Restore cache: %s', hass.data[DATA_RESTORE_CACHE]) - assert len(hass.data[DATA_RESTORE_CACHE]) == len(states), \ + _LOGGER.debug('Restore cache: %s', hass.data[key]) + assert len(hass.data[key]) == len(states), \ "Duplicate entity_id? {}".format(states) hass.state = ha.CoreState.starting mock_component(hass, recorder.DOMAIN) diff --git a/tests/components/test_alexa.py b/tests/components/test_alexa.py index 47a3e086d29..eb8391c3e0d 100644 --- a/tests/components/test_alexa.py +++ b/tests/components/test_alexa.py @@ -47,10 +47,14 @@ def alexa_client(loop, hass, test_client): "uid": "uuid" } }, - "intents": { + } + })) + assert loop.run_until_complete(async_setup_component( + hass, 'intent_script', { + 'intent_script': { "WhereAreWeIntent": { "speech": { - "type": "plaintext", + "type": "plain", "text": """ {%- if is_state("device_tracker.paulus", "home") @@ -69,19 +73,19 @@ def alexa_client(loop, hass, test_client): }, "GetZodiacHoroscopeIntent": { "speech": { - "type": "plaintext", + "type": "plain", "text": "You told us your sign is {{ ZodiacSign }}.", } }, "AMAZON.PlaybackAction": { "speech": { - "type": "plaintext", + "type": "plain", "text": "Playing {{ object_byArtist_name }}.", } }, "CallServiceIntent": { "speech": { - "type": "plaintext", + "type": "plain", "text": "Service called", }, "action": { @@ -93,8 +97,7 @@ def alexa_client(loop, hass, test_client): } } } - } - })) + })) return loop.run_until_complete(test_client(hass.http.app)) diff --git a/tests/components/test_apiai.py b/tests/components/test_apiai.py index f5624f3c209..0c15326bbfc 100644 --- a/tests/components/test_apiai.py +++ b/tests/components/test_apiai.py @@ -57,14 +57,15 @@ def setUpModule(): hass.services.register("test", "apiai", mock_service) - setup.setup_component(hass, apiai.DOMAIN, { - # Key is here to verify we allow other keys in config too - "homeassistant": {}, - "apiai": { - "intents": { - "WhereAreWeIntent": { - "speech": - """ + assert setup.setup_component(hass, apiai.DOMAIN, { + "apiai": {}, + }) + assert setup.setup_component(hass, "intent_script", { + "intent_script": { + "WhereAreWeIntent": { + "speech": { + "type": "plain", + "text": """ {%- if is_state("device_tracker.paulus", "home") and is_state("device_tracker.anne_therese", "home") -%} @@ -77,19 +78,25 @@ def setUpModule(): }} {% endif %} """, + } + }, + "GetZodiacHoroscopeIntent": { + "speech": { + "type": "plain", + "text": "You told us your sign is {{ ZodiacSign }}.", + } + }, + "CallServiceIntent": { + "speech": { + "type": "plain", + "text": "Service called", }, - "GetZodiacHoroscopeIntent": { - "speech": "You told us your sign is {{ ZodiacSign }}.", - }, - "CallServiceIntent": { - "speech": "Service called", - "action": { - "service": "test.apiai", - "data_template": { - "hello": "{{ ZodiacSign }}" - }, - "entity_id": "switch.test", - } + "action": { + "service": "test.apiai", + "data_template": { + "hello": "{{ ZodiacSign }}" + }, + "entity_id": "switch.test", } } } @@ -509,5 +516,4 @@ class TestApiai(unittest.TestCase): self.assertEqual(200, req.status_code) text = req.json().get("speech") self.assertEqual( - "Intent 'unknown' is not yet configured within Home Assistant.", - text) + "This intent is not yet configured within Home Assistant.", text) diff --git a/tests/components/test_conversation.py b/tests/components/test_conversation.py index 65ce95ee8e9..138ae1668f8 100644 --- a/tests/components/test_conversation.py +++ b/tests/components/test_conversation.py @@ -1,16 +1,18 @@ """The tests for the Conversation component.""" # pylint: disable=protected-access +import asyncio import unittest from unittest.mock import patch from homeassistant.core import callback -from homeassistant.setup import setup_component +from homeassistant.setup import setup_component, async_setup_component import homeassistant.components as core_components from homeassistant.components import conversation from homeassistant.const import ATTR_ENTITY_ID from homeassistant.util.async import run_coroutine_threadsafe +from homeassistant.helpers import intent -from tests.common import get_test_home_assistant, assert_setup_component +from tests.common import get_test_home_assistant, async_mock_intent class TestConversation(unittest.TestCase): @@ -25,10 +27,9 @@ class TestConversation(unittest.TestCase): self.assertTrue(run_coroutine_threadsafe( core_components.async_setup(self.hass, {}), self.hass.loop ).result()) - with assert_setup_component(0): - self.assertTrue(setup_component(self.hass, conversation.DOMAIN, { - conversation.DOMAIN: {} - })) + self.assertTrue(setup_component(self.hass, conversation.DOMAIN, { + conversation.DOMAIN: {} + })) # pylint: disable=invalid-name def tearDown(self): @@ -119,44 +120,131 @@ class TestConversation(unittest.TestCase): self.assertFalse(mock_call.called) -class TestConfiguration(unittest.TestCase): - """Test the conversation configuration component.""" +@asyncio.coroutine +def test_calling_intent(hass): + """Test calling an intent from a conversation.""" + intents = async_mock_intent(hass, 'OrderBeer') - # pylint: disable=invalid-name - def setUp(self): - """Setup things to be run when tests are started.""" - self.hass = get_test_home_assistant() - self.assertTrue(setup_component(self.hass, conversation.DOMAIN, { - conversation.DOMAIN: { - 'test_2': { - 'sentence': 'switch boolean', - 'action': { - 'service': 'input_boolean.toggle' - } - } + result = yield from async_setup_component(hass, 'conversation', { + 'conversation': { + 'intents': { + 'OrderBeer': [ + 'I would like the {type} beer' + ] } - })) + } + }) + assert result - # pylint: disable=invalid-name - def tearDown(self): - """Stop everything that was started.""" - self.hass.stop() + yield from hass.services.async_call( + 'conversation', 'process', { + conversation.ATTR_TEXT: 'I would like the Grolsch beer' + }) + yield from hass.async_block_till_done() - def test_custom(self): - """Setup and perform good turn on requests.""" - calls = [] + assert len(intents) == 1 + intent = intents[0] + assert intent.platform == 'conversation' + assert intent.intent_type == 'OrderBeer' + assert intent.slots == {'type': {'value': 'Grolsch'}} + assert intent.text_input == 'I would like the Grolsch beer' - @callback - def record_call(service): - """Recorder for a call.""" - calls.append(service) - self.hass.services.register('input_boolean', 'toggle', record_call) +@asyncio.coroutine +def test_register_before_setup(hass): + """Test calling an intent from a conversation.""" + intents = async_mock_intent(hass, 'OrderBeer') - event_data = {conversation.ATTR_TEXT: 'switch boolean'} - self.assertTrue(self.hass.services.call( - conversation.DOMAIN, 'process', event_data, True)) + hass.components.conversation.async_register('OrderBeer', [ + 'A {type} beer, please' + ]) - call = calls[-1] - self.assertEqual('input_boolean', call.domain) - self.assertEqual('toggle', call.service) + result = yield from async_setup_component(hass, 'conversation', { + 'conversation': { + 'intents': { + 'OrderBeer': [ + 'I would like the {type} beer' + ] + } + } + }) + assert result + + yield from hass.services.async_call( + 'conversation', 'process', { + conversation.ATTR_TEXT: 'A Grolsch beer, please' + }) + yield from hass.async_block_till_done() + + assert len(intents) == 1 + intent = intents[0] + assert intent.platform == 'conversation' + assert intent.intent_type == 'OrderBeer' + assert intent.slots == {'type': {'value': 'Grolsch'}} + assert intent.text_input == 'A Grolsch beer, please' + + yield from hass.services.async_call( + 'conversation', 'process', { + conversation.ATTR_TEXT: 'I would like the Grolsch beer' + }) + yield from hass.async_block_till_done() + + assert len(intents) == 2 + intent = intents[1] + assert intent.platform == 'conversation' + assert intent.intent_type == 'OrderBeer' + assert intent.slots == {'type': {'value': 'Grolsch'}} + assert intent.text_input == 'I would like the Grolsch beer' + + +@asyncio.coroutine +def test_http_processing_intent(hass, test_client): + """Test processing intent via HTTP API.""" + class TestIntentHandler(intent.IntentHandler): + intent_type = 'OrderBeer' + + @asyncio.coroutine + def async_handle(self, intent): + """Handle the intent.""" + response = intent.create_response() + response.async_set_speech( + "I've ordered a {}!".format(intent.slots['type']['value'])) + response.async_set_card( + "Beer ordered", + "You chose a {}.".format(intent.slots['type']['value'])) + return response + + intent.async_register(hass, TestIntentHandler()) + + result = yield from async_setup_component(hass, 'conversation', { + 'conversation': { + 'intents': { + 'OrderBeer': [ + 'I would like the {type} beer' + ] + } + } + }) + assert result + + client = yield from test_client(hass.http.app) + resp = yield from client.post('/api/conversation/process', json={ + 'text': 'I would like the Grolsch beer' + }) + + assert resp.status == 200 + data = yield from resp.json() + + assert data == { + 'card': { + 'simple': { + 'content': 'You chose a Grolsch.', + 'title': 'Beer ordered' + }}, + 'speech': { + 'plain': { + 'extra_data': None, + 'speech': "I've ordered a Grolsch!" + } + } + } diff --git a/tests/components/test_demo.py b/tests/components/test_demo.py index 1bb39b053a5..93aac65ecb5 100644 --- a/tests/components/test_demo.py +++ b/tests/components/test_demo.py @@ -1,52 +1,62 @@ """The tests for the Demo component.""" +import asyncio import json import os -import unittest -from homeassistant.setup import setup_component +import pytest + +from homeassistant.setup import async_setup_component from homeassistant.components import demo, device_tracker from homeassistant.remote import JSONEncoder -from tests.common import mock_http_component, get_test_home_assistant + +@pytest.fixture +def minimize_demo_platforms(hass): + """Cleanup demo component for tests.""" + orig = demo.COMPONENTS_WITH_DEMO_PLATFORM + demo.COMPONENTS_WITH_DEMO_PLATFORM = [ + 'switch', 'light', 'media_player'] + + yield + + demo.COMPONENTS_WITH_DEMO_PLATFORM = orig -class TestDemo(unittest.TestCase): - """Test the Demo component.""" +@pytest.fixture(autouse=True) +def demo_cleanup(hass): + """Clean up device tracker demo file.""" + yield + try: + os.remove(hass.config.path(device_tracker.YAML_DEVICES)) + except FileNotFoundError: + pass - def setUp(self): # pylint: disable=invalid-name - """Setup things to be run when tests are started.""" - self.hass = get_test_home_assistant() - mock_http_component(self.hass) - def tearDown(self): # pylint: disable=invalid-name - """Stop everything that was started.""" - self.hass.stop() +@asyncio.coroutine +def test_if_demo_state_shows_by_default(hass, minimize_demo_platforms): + """Test if demo state shows if we give no configuration.""" + yield from async_setup_component(hass, demo.DOMAIN, {demo.DOMAIN: {}}) - try: - os.remove(self.hass.config.path(device_tracker.YAML_DEVICES)) - except FileNotFoundError: - pass + assert hass.states.get('a.Demo_Mode') is not None - def test_if_demo_state_shows_by_default(self): - """Test if demo state shows if we give no configuration.""" - setup_component(self.hass, demo.DOMAIN, {demo.DOMAIN: {}}) - self.assertIsNotNone(self.hass.states.get('a.Demo_Mode')) +@asyncio.coroutine +def test_hiding_demo_state(hass, minimize_demo_platforms): + """Test if you can hide the demo card.""" + yield from async_setup_component(hass, demo.DOMAIN, { + demo.DOMAIN: {'hide_demo_state': 1}}) - def test_hiding_demo_state(self): - """Test if you can hide the demo card.""" - setup_component(self.hass, demo.DOMAIN, { - demo.DOMAIN: {'hide_demo_state': 1}}) + assert hass.states.get('a.Demo_Mode') is None - self.assertIsNone(self.hass.states.get('a.Demo_Mode')) - def test_all_entities_can_be_loaded_over_json(self): - """Test if you can hide the demo card.""" - setup_component(self.hass, demo.DOMAIN, { - demo.DOMAIN: {'hide_demo_state': 1}}) +@asyncio.coroutine +def test_all_entities_can_be_loaded_over_json(hass): + """Test if you can hide the demo card.""" + yield from async_setup_component(hass, demo.DOMAIN, { + demo.DOMAIN: {'hide_demo_state': 1}}) - try: - json.dumps(self.hass.states.all(), cls=JSONEncoder) - except Exception: - self.fail('Unable to convert all demo entities to JSON. ' - 'Wrong data in state machine!') + try: + json.dumps(hass.states.async_all(), cls=JSONEncoder) + except Exception: + pytest.fail('Unable to convert all demo entities to JSON. ' + 'Wrong data in state machine!') diff --git a/tests/components/test_intent_script.py b/tests/components/test_intent_script.py new file mode 100644 index 00000000000..2c7a03e645a --- /dev/null +++ b/tests/components/test_intent_script.py @@ -0,0 +1,45 @@ +"""Test intent_script component.""" +import asyncio + +from homeassistant.bootstrap import async_setup_component +from homeassistant.helpers import intent + +from tests.common import async_mock_service + + +@asyncio.coroutine +def test_intent_script(hass): + """Test intent scripts work.""" + calls = async_mock_service(hass, 'test', 'service') + + yield from async_setup_component(hass, 'intent_script', { + 'intent_script': { + 'HelloWorld': { + 'action': { + 'service': 'test.service', + 'data_template': { + 'hello': '{{ name }}' + } + }, + 'card': { + 'title': 'Hello {{ name }}', + 'content': 'Content for {{ name }}', + }, + 'speech': { + 'text': 'Good morning {{ name }}' + } + } + } + }) + + response = yield from intent.async_handle( + hass, 'test', 'HelloWorld', {'name': {'value': 'Paulus'}} + ) + + assert len(calls) == 1 + assert calls[0].data['hello'] == 'Paulus' + + assert response.speech['plain']['speech'] == 'Good morning Paulus' + + assert response.card['simple']['title'] == 'Hello Paulus' + assert response.card['simple']['content'] == 'Content for Paulus' diff --git a/tests/components/test_shopping_list.py b/tests/components/test_shopping_list.py new file mode 100644 index 00000000000..867e695e2d5 --- /dev/null +++ b/tests/components/test_shopping_list.py @@ -0,0 +1,61 @@ +"""Test shopping list component.""" +import asyncio + +from homeassistant.bootstrap import async_setup_component +from homeassistant.helpers import intent + + +@asyncio.coroutine +def test_add_item(hass): + """Test adding an item intent.""" + yield from async_setup_component(hass, 'shopping_list', {}) + + response = yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'beer'}} + ) + + assert response.speech['plain']['speech'] == \ + "I've added beer to your shopping list" + + +@asyncio.coroutine +def test_recent_items_intent(hass): + """Test recent items.""" + yield from async_setup_component(hass, 'shopping_list', {}) + + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'beer'}} + ) + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'wine'}} + ) + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'soda'}} + ) + + response = yield from intent.async_handle( + hass, 'test', 'HassShoppingListLastItems' + ) + + assert response.speech['plain']['speech'] == \ + "These are the top 5 items in your shopping list: soda, wine, beer" + + +@asyncio.coroutine +def test_api(hass, test_client): + """Test the API.""" + yield from async_setup_component(hass, 'shopping_list', {}) + + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'beer'}} + ) + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'wine'}} + ) + + client = yield from test_client(hass.http.app) + resp = yield from client.get('/api/shopping_list') + + assert resp.status == 200 + data = yield from resp.json() + assert data == ['beer', 'wine'] diff --git a/tests/components/test_snips.py b/tests/components/test_snips.py index 5687723e17a..5e49bbd0382 100644 --- a/tests/components/test_snips.py +++ b/tests/components/test_snips.py @@ -2,7 +2,7 @@ import asyncio from homeassistant.bootstrap import async_setup_component -from tests.common import async_fire_mqtt_message, async_mock_service +from tests.common import async_fire_mqtt_message, async_mock_intent EXAMPLE_MSG = """ { @@ -16,7 +16,7 @@ EXAMPLE_MSG = """ "slotName": "light_color", "value": { "kind": "Custom", - "value": "blue" + "value": "green" } } ] @@ -27,27 +27,19 @@ EXAMPLE_MSG = """ @asyncio.coroutine def test_snips_call_action(hass, mqtt_mock): """Test calling action via Snips.""" - calls = async_mock_service(hass, 'test', 'service') - result = yield from async_setup_component(hass, "snips", { - "snips": { - "intents": { - "Lights": { - "action": { - "service": "test.service", - "data_template": { - "color": "{{ light_color }}" - } - } - } - } - } + "snips": {}, }) assert result + intents = async_mock_intent(hass, 'Lights') + async_fire_mqtt_message(hass, 'hermes/nlu/intentParsed', EXAMPLE_MSG) yield from hass.async_block_till_done() - assert len(calls) == 1 - call = calls[0] - assert call.data.get('color') == 'blue' + assert len(intents) == 1 + intent = intents[0] + assert intent.platform == 'snips' + assert intent.intent_type == 'Lights' + assert intent.slots == {'light_color': {'value': 'green'}} + assert intent.text_input == 'turn the lights green' From 8e8ec7a7c354f85bb51a006ba0b131b20632b674 Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Sat, 22 Jul 2017 09:21:38 -0400 Subject: [PATCH 065/118] Remove code in wink.py overwriting hass.data configurator (#8595) --- homeassistant/components/wink.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/wink.py b/homeassistant/components/wink.py index 58a6f51b67b..1783d4bd79a 100644 --- a/homeassistant/components/wink.py +++ b/homeassistant/components/wink.py @@ -103,7 +103,7 @@ def _read_config_file(file_path): def _request_app_setup(hass, config): """Assist user with configuring the Wink dev application.""" - hass.data['configurator'] = True + hass.data[DOMAIN]['configurator'] = True configurator = get_component('configurator') # pylint: disable=unused-argument @@ -151,7 +151,7 @@ def _request_app_setup(hass, config): def _request_oauth_completion(hass, config): """Request user complete Wink OAuth2 flow.""" - hass.data['configurator'] = True + hass.data[DOMAIN]['configurator'] = True configurator = get_component('configurator') if DOMAIN in hass.data[DOMAIN]['configuring']: configurator.notify_errors( From b4f392b181fd5f87ea1ac0f1c7029cce9e90f33c Mon Sep 17 00:00:00 2001 From: Teemu R Date: Sat, 22 Jul 2017 19:36:14 +0200 Subject: [PATCH 066/118] bump python-mirobo version for more robust protocol handling, make the platform to update on startup (#8602) --- homeassistant/components/switch/xiaomi_vacuum.py | 8 ++++---- requirements_all.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/switch/xiaomi_vacuum.py b/homeassistant/components/switch/xiaomi_vacuum.py index 20906dd8df1..393cabb72b9 100644 --- a/homeassistant/components/switch/xiaomi_vacuum.py +++ b/homeassistant/components/switch/xiaomi_vacuum.py @@ -22,7 +22,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME): cv.string, }) -REQUIREMENTS = ['python-mirobo==0.1.1'] +REQUIREMENTS = ['python-mirobo==0.1.2'] # pylint: disable=unused-argument @@ -32,7 +32,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): name = config.get(CONF_NAME) token = config.get(CONF_TOKEN) - add_devices_callback([MiroboSwitch(name, host, token)]) + add_devices_callback([MiroboSwitch(name, host, token)], True) class MiroboSwitch(SwitchDevice): @@ -107,7 +107,7 @@ class MiroboSwitch(SwitchDevice): def update(self): """Fetch state from the device.""" - from mirobo import VacuumException + from mirobo import DeviceException try: state = self.vacuum.status() _LOGGER.debug("got state from the vacuum: %s", state) @@ -120,5 +120,5 @@ class MiroboSwitch(SwitchDevice): self._state = state.state_code self._is_on = state.is_on - except VacuumException as ex: + except DeviceException as ex: _LOGGER.error("Got exception while fetching the state: %s", ex) diff --git a/requirements_all.txt b/requirements_all.txt index 6bfc3a70ee6..8e5d3d52fa3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -718,7 +718,7 @@ python-juicenet==0.0.5 # python-lirc==1.2.3 # homeassistant.components.switch.xiaomi_vacuum -python-mirobo==0.1.1 +python-mirobo==0.1.2 # homeassistant.components.media_player.mpd python-mpd2==0.5.5 From 1807b45222fd82ba4b78fa8e700b7bee8e974c3b Mon Sep 17 00:00:00 2001 From: Sean Gollschewsky Date: Sat, 22 Jul 2017 18:50:31 +0100 Subject: [PATCH 067/118] Binary sensor ping fixed for hassio (#8573) * Add support for multiple ping utilities. * Added support for differing flavours of ping included with different distributions (specifically alpine linux for hassio's homeassistant). * Updated as per comments in PR --- homeassistant/components/binary_sensor/ping.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/binary_sensor/ping.py b/homeassistant/components/binary_sensor/ping.py index cb5bc4333a2..1919c7ab64d 100644 --- a/homeassistant/components/binary_sensor/ping.py +++ b/homeassistant/components/binary_sensor/ping.py @@ -35,6 +35,9 @@ SCAN_INTERVAL = timedelta(minutes=5) PING_MATCHER = re.compile( r'(?P\d+.\d+)\/(?P\d+.\d+)\/(?P\d+.\d+)\/(?P\d+.\d+)') +PING_MATCHER_BUSYBOX = re.compile( + r'(?P\d+.\d+)\/(?P\d+.\d+)\/(?P\d+.\d+)') + WIN32_PING_MATCHER = re.compile( r'(?P\d+)ms.+(?P\d+)ms.+(?P\d+)ms') @@ -126,7 +129,14 @@ class PingData(object): 'avg': rtt_avg, 'max': rtt_max, 'mdev': ''} - + if 'max/' not in str(out): + match = PING_MATCHER_BUSYBOX.search(str(out).split('\n')[-1]) + rtt_min, rtt_avg, rtt_max = match.groups() + return { + 'min': rtt_min, + 'avg': rtt_avg, + 'max': rtt_max, + 'mdev': ''} match = PING_MATCHER.search(str(out).split('\n')[-1]) rtt_min, rtt_avg, rtt_max, rtt_mdev = match.groups() return { From 2f08a91fdd7b6dae9976cb46741466bd4216e018 Mon Sep 17 00:00:00 2001 From: Open Home Automation Date: Sat, 22 Jul 2017 20:00:13 +0200 Subject: [PATCH 068/118] Simplified percent conversion, better logging (#8568) * Simplified percent conversion, better logging * Unnecessary pass statement (unnecessary-pass) --- homeassistant/components/sensor/knx.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/sensor/knx.py b/homeassistant/components/sensor/knx.py index d4752666821..80a88ca925a 100644 --- a/homeassistant/components/sensor/knx.py +++ b/homeassistant/components/sensor/knx.py @@ -160,8 +160,12 @@ def convert_float(raw_value): Defined in KNX 3.7.2 - 3.10 """ from knxip.conversion import knx2_to_float + from knxip.core import KNXException - return knx2_to_float(raw_value) + try: + return knx2_to_float(raw_value) + except KNXException as exception: + _LOGGER.error("Can't convert %s to float (%s)", raw_value, exception) def convert_percent(raw_value): @@ -170,14 +174,11 @@ def convert_percent(raw_value): 1byte percentage scaled KNX Telegram. Defined in KNX 3.7.2 - 3.10. """ - summed_value = 0 + value = 0 try: - # convert raw value in bytes - for val in raw_value: - summed_value *= 256 - summed_value += val - except TypeError: + value = raw_value[0] + except (IndexError, ValueError): # pknx returns a non-iterable type for unsuccessful reads - pass + _LOGGER.error("Can't convert %s to percent value", raw_value) - return round(summed_value * 100 / 255) + return round(value * 100 / 255) From 9043895407c3d4876f96764ef316bd55f17997ea Mon Sep 17 00:00:00 2001 From: Thomas Klingbeil Date: Sat, 22 Jul 2017 20:34:58 +0200 Subject: [PATCH 069/118] make attributes in the fritzdect module easier to process (#8436) * make attributes in the fritzdect module easier to process * remove spaces in attribute names * move units to separate attributes * make attributes in the fritzdect module easier to process * remove spaces in attribute names * move units to separate attributes * Use new python formating syntax and attribute constant * Shorten too long line * Fix indent --- homeassistant/components/switch/fritzdect.py | 34 ++++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/switch/fritzdect.py b/homeassistant/components/switch/fritzdect.py index fc185c9f6a3..5893b3419d5 100644 --- a/homeassistant/components/switch/fritzdect.py +++ b/homeassistant/components/switch/fritzdect.py @@ -12,7 +12,7 @@ from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA) from homeassistant.const import ( CONF_HOST, CONF_PASSWORD, CONF_USERNAME) import homeassistant.helpers.config_validation as cv -from homeassistant.const import TEMP_CELSIUS, STATE_UNKNOWN +from homeassistant.const import TEMP_CELSIUS, ATTR_TEMPERATURE, STATE_UNKNOWN REQUIREMENTS = ['fritzhome==1.0.2'] @@ -21,13 +21,15 @@ _LOGGER = logging.getLogger(__name__) # Standard Fritz Box IP DEFAULT_HOST = 'fritz.box' -ATTR_CURRENT_CONSUMPTION = 'Current Consumption' -ATTR_CURRENT_CONSUMPTION_UNIT = 'W' +ATTR_CURRENT_CONSUMPTION = 'current_consumption' +ATTR_CURRENT_CONSUMPTION_UNIT = 'current_consumption_unit' +ATTR_CURRENT_CONSUMPTION_UNIT_VALUE = 'W' -ATTR_TOTAL_CONSUMPTION = 'Total Consumption' -ATTR_TOTAL_CONSUMPTION_UNIT = 'kWh' +ATTR_TOTAL_CONSUMPTION = 'total_consumption' +ATTR_TOTAL_CONSUMPTION_UNIT = 'total_consumption_unit' +ATTR_TOTAL_CONSUMPTION_UNIT_VALUE = 'kWh' -ATTR_TEMPERATURE = 'Temperature' +ATTR_TEMPERATURE_UNIT = 'temperature_unit' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, @@ -86,17 +88,21 @@ class FritzDectSwitch(SwitchDevice): if self.data.has_powermeter and \ self.data.current_consumption != STATE_UNKNOWN and \ self.data.total_consumption != STATE_UNKNOWN: - attrs[ATTR_CURRENT_CONSUMPTION] = "%.1f %s" % \ - (self.data.current_consumption, ATTR_CURRENT_CONSUMPTION_UNIT) - attrs[ATTR_TOTAL_CONSUMPTION] = "%.3f %s" % \ - (self.data.total_consumption, ATTR_TOTAL_CONSUMPTION_UNIT) + attrs[ATTR_CURRENT_CONSUMPTION] = "{:.1f}".format( + self.data.current_consumption) + attrs[ATTR_CURRENT_CONSUMPTION_UNIT] = "{}".format( + ATTR_CURRENT_CONSUMPTION_UNIT_VALUE) + attrs[ATTR_TOTAL_CONSUMPTION] = "{:.3f}".format( + self.data.total_consumption) + attrs[ATTR_TOTAL_CONSUMPTION_UNIT] = "{}".format( + ATTR_TOTAL_CONSUMPTION_UNIT_VALUE) if self.data.has_temperature and \ self.data.temperature != STATE_UNKNOWN: - attrs[ATTR_TEMPERATURE] = "%.1f %s" % \ - (self.units.temperature(self.data.temperature, TEMP_CELSIUS), - self.units.temperature_unit) - + attrs[ATTR_TEMPERATURE] = "{}".format( + self.units.temperature(self.data.temperature, TEMP_CELSIUS)) + attrs[ATTR_TEMPERATURE_UNIT] = "{}".format( + self.units.temperature_unit) return attrs @property From dac9716cf4d2e92415948664d05204591eafb43d Mon Sep 17 00:00:00 2001 From: Chia-liang Kao Date: Sun, 23 Jul 2017 03:22:49 -0500 Subject: [PATCH 070/118] Fix STATION_SCHEMA validation on longitude (#8610) --- homeassistant/components/sensor/citybikes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/citybikes.py b/homeassistant/components/sensor/citybikes.py index 4cb532d26eb..32b82b15631 100644 --- a/homeassistant/components/sensor/citybikes.py +++ b/homeassistant/components/sensor/citybikes.py @@ -84,7 +84,7 @@ STATION_SCHEMA = vol.Schema({ vol.Required(ATTR_FREE_BIKES): cv.positive_int, vol.Required(ATTR_EMPTY_SLOTS): vol.Any(cv.positive_int, None), vol.Required(ATTR_LATITUDE): cv.latitude, - vol.Required(ATTR_LONGITUDE): cv.latitude, + vol.Required(ATTR_LONGITUDE): cv.longitude, vol.Required(ATTR_ID): cv.string, vol.Required(ATTR_NAME): cv.string, vol.Required(ATTR_TIMESTAMP): cv.string, From c6bf529d38d639337d5b9f8995f4aa6acddc826a Mon Sep 17 00:00:00 2001 From: Koen Ekelschot Date: Sun, 23 Jul 2017 15:59:27 +0200 Subject: [PATCH 071/118] Allow set_cover_position in scenes (#8613) --- homeassistant/helpers/state.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/homeassistant/helpers/state.py b/homeassistant/helpers/state.py index 19113f243d2..93953fcd69e 100644 --- a/homeassistant/helpers/state.py +++ b/homeassistant/helpers/state.py @@ -24,17 +24,19 @@ from homeassistant.components.climate import ( from homeassistant.components.climate.ecobee import ( ATTR_FAN_MIN_ON_TIME, SERVICE_SET_FAN_MIN_ON_TIME, ATTR_RESUME_ALL, SERVICE_RESUME_PROGRAM) +from homeassistant.components.cover import ( + ATTR_POSITION) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_OPTION, ATTR_TEMPERATURE, SERVICE_ALARM_ARM_AWAY, SERVICE_ALARM_ARM_HOME, SERVICE_ALARM_DISARM, SERVICE_ALARM_TRIGGER, SERVICE_LOCK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY, SERVICE_MEDIA_SEEK, SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_UNLOCK, SERVICE_VOLUME_MUTE, SERVICE_VOLUME_SET, SERVICE_OPEN_COVER, - SERVICE_CLOSE_COVER, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, - STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, STATE_CLOSED, STATE_HOME, - STATE_LOCKED, STATE_NOT_HOME, STATE_OFF, STATE_ON, STATE_OPEN, - STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, STATE_UNLOCKED, - SERVICE_SELECT_OPTION) + SERVICE_CLOSE_COVER, SERVICE_SET_COVER_POSITION, STATE_ALARM_ARMED_AWAY, + STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, + STATE_CLOSED, STATE_HOME, STATE_LOCKED, STATE_NOT_HOME, STATE_OFF, + STATE_ON, STATE_OPEN, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, + STATE_UNLOCKED, SERVICE_SELECT_OPTION) from homeassistant.core import State from homeassistant.util.async import run_coroutine_threadsafe @@ -63,7 +65,8 @@ SERVICE_ATTRIBUTES = { SERVICE_SET_AUX_HEAT: [ATTR_AUX_HEAT], SERVICE_SELECT_SOURCE: [ATTR_INPUT_SOURCE], SERVICE_SEND_IR_CODE: [ATTR_IR_CODE], - SERVICE_SELECT_OPTION: [ATTR_OPTION] + SERVICE_SELECT_OPTION: [ATTR_OPTION], + SERVICE_SET_COVER_POSITION: [ATTR_POSITION] } # Update this dict when new services are added to HA. From 77d8e393a1e4da040fe53c8b79cada5f0cde7365 Mon Sep 17 00:00:00 2001 From: cribbstechnologies Date: Sun, 23 Jul 2017 14:19:58 -0400 Subject: [PATCH 072/118] better but still not great (#8618) --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 66c9cedea74..40a393517da 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -Home Assistant |Build Status| |Coverage Status| |Join the chat at https://gitter.im/home-assistant/home-assistant| |Join the dev chat at https://gitter.im/home-assistant/home-assistant/devs| +Home Assistant |Build Status| |Coverage Status| | Join the chat `at discord `_ | Join the dev chat `at discord `_ | ============================================================================================================================================================================================== Home Assistant is a home automation platform running on Python 3. It is able to track and control all devices at home and offer a platform for automating control. From cc2de5e1dceb345e0286084309f1a7b79edc86ea Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 23 Jul 2017 20:20:23 +0200 Subject: [PATCH 073/118] Upgrade youtube_dl to 2017.7.23 (#8617) --- homeassistant/components/media_extractor.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/media_extractor.py b/homeassistant/components/media_extractor.py index 559af46e9f6..cb00c8fe035 100644 --- a/homeassistant/components/media_extractor.py +++ b/homeassistant/components/media_extractor.py @@ -15,7 +15,7 @@ from homeassistant.components.media_player import ( from homeassistant.config import load_yaml_config_file from homeassistant.helpers import config_validation as cv -REQUIREMENTS = ['youtube_dl==2017.7.9'] +REQUIREMENTS = ['youtube_dl==2017.7.23'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 8e5d3d52fa3..97066df38da 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -971,7 +971,7 @@ yeelight==0.3.0 yeelightsunflower==0.0.8 # homeassistant.components.media_extractor -youtube_dl==2017.7.9 +youtube_dl==2017.7.23 # homeassistant.components.light.zengge zengge==0.2 From 486bcc4cae604a8d4ad6d499ff22d3e6ef9c4d50 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 23 Jul 2017 20:20:38 +0200 Subject: [PATCH 074/118] Upgrade mypy to 0.520 (#8616) --- requirements_test.txt | 2 +- requirements_test_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements_test.txt b/requirements_test.txt index 95f9bfef329..cc54c21c18b 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -3,7 +3,7 @@ # new version flake8==3.3 pylint==1.6.5 -mypy==0.511 +mypy==0.520 pydocstyle==1.1.1 coveralls>=1.1 pytest>=2.9.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 491f5574b32..9d2842c7bbb 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -4,7 +4,7 @@ # new version flake8==3.3 pylint==1.6.5 -mypy==0.511 +mypy==0.520 pydocstyle==1.1.1 coveralls>=1.1 pytest>=2.9.2 From 5d810dae86aa98c527e82cab1fb10a607dcb7851 Mon Sep 17 00:00:00 2001 From: Phil Hawthorne Date: Mon, 24 Jul 2017 06:42:41 +1000 Subject: [PATCH 075/118] REST binary sensor value_template optional (#8596) According to the documentation, the `value_template` for the REST binary_sensor is not required. However, if you don't provide this when setting up a binary sensor, the component fails. Looks like a variable was not being set, which I've now included. This should make the REST binary sensor act the same way as the REST sensor now. --- homeassistant/components/binary_sensor/rest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/components/binary_sensor/rest.py b/homeassistant/components/binary_sensor/rest.py index abdbc8251c7..6d1745700bd 100644 --- a/homeassistant/components/binary_sensor/rest.py +++ b/homeassistant/components/binary_sensor/rest.py @@ -107,6 +107,8 @@ class RestBinarySensor(BinarySensorDevice): if self.rest.data is None: return False + response = self.rest.data + if self._value_template is not None: response = self._value_template.\ async_render_with_possible_json_value(self.rest.data, False) From 3fec2955a5ee4f4ab9e1354fb94071a639fc9ac1 Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Mon, 24 Jul 2017 02:46:23 -0400 Subject: [PATCH 076/118] Bumped Amcrest version (#8624) --- homeassistant/components/amcrest.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/amcrest.py b/homeassistant/components/amcrest.py index 9760ee5d607..157b9574a06 100644 --- a/homeassistant/components/amcrest.py +++ b/homeassistant/components/amcrest.py @@ -17,7 +17,7 @@ from homeassistant.const import ( from homeassistant.helpers import discovery import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['amcrest==1.2.0'] +REQUIREMENTS = ['amcrest==1.2.1'] DEPENDENCIES = ['ffmpeg'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 97066df38da..10036a03615 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -61,7 +61,7 @@ aiopvapi==1.4 alarmdecoder==0.12.3 # homeassistant.components.amcrest -amcrest==1.2.0 +amcrest==1.2.1 # homeassistant.components.media_player.anthemav anthemav==1.1.8 From 1831a7da68d7fc6902a88d31ab320a729624bb9e Mon Sep 17 00:00:00 2001 From: Daniel Schaal Date: Mon, 24 Jul 2017 08:47:38 +0200 Subject: [PATCH 077/118] Check if /dev/input/by-id exists (#8601) --- homeassistant/components/keyboard_remote.py | 25 ++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/keyboard_remote.py b/homeassistant/components/keyboard_remote.py index 88d406ace0b..5a81f6d2a9e 100644 --- a/homeassistant/components/keyboard_remote.py +++ b/homeassistant/components/keyboard_remote.py @@ -94,20 +94,25 @@ class KeyboardRemote(threading.Thread): if self.dev is not None: _LOGGER.debug("Keyboard connected, %s", self.device_id) else: - id_folder = '/dev/input/by-id/' - device_names = [InputDevice(file_name).name - for file_name in list_devices()] _LOGGER.debug( 'Keyboard not connected, %s.\n\ - Check /dev/input/event* permissions.\ - Possible device names are:\n %s.\n \ - Possible device descriptors are %s:\n %s', - self.device_id, - device_names, - id_folder, - os.listdir(id_folder) + Check /dev/input/event* permissions.', + self.device_id ) + id_folder = '/dev/input/by-id/' + + if os.path.isdir(id_folder): + device_names = [InputDevice(file_name).name + for file_name in list_devices()] + _LOGGER.debug( + 'Possible device names are:\n %s.\n \ + Possible device descriptors are %s:\n %s', + device_names, + id_folder, + os.listdir(id_folder) + ) + threading.Thread.__init__(self) self.stopped = threading.Event() self.hass = hass From 4b449f5f93aa41f7be1d7d23f2223587bb16551f Mon Sep 17 00:00:00 2001 From: Phil Cole Date: Mon, 24 Jul 2017 08:48:20 +0200 Subject: [PATCH 078/118] Tado Fix #8606 (#8621) Handle case where 'mode' and 'fanSpeed' are missing JSON. Based on changes in commit https://github.com/wmalgadey/tado_component/commit/adfb608f86b8bf4c1c43e71b4067cbfe1de9ba85 --- homeassistant/components/climate/tado.py | 47 ++++++++++++++---------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/climate/tado.py b/homeassistant/components/climate/tado.py index 8a2e6621af3..459cbec0497 100644 --- a/homeassistant/components/climate/tado.py +++ b/homeassistant/components/climate/tado.py @@ -273,31 +273,38 @@ class TadoClimate(ClimateDevice): else: self._device_is_active = True + overlay = False + overlay_data = None + termination = self._current_operation + cooling = False + fan_speed = CONST_MODE_OFF + + if 'overlay' in data: + overlay_data = data['overlay'] + overlay = overlay_data is not None + + if overlay: + termination = overlay_data['termination']['type'] + + if 'setting' in overlay_data: + setting_data = overlay_data['setting'] + setting = setting is not None + + if setting: + if 'mode' in setting_data: + cooling = setting_data['mode'] == 'COOL' + + if 'fanSpeed' in setting_data: + fan_speed = setting_data['fanSpeed'] + if self._device_is_active: - overlay = False - overlay_data = None - termination = self._current_operation - cooling = False - fan_speed = CONST_MODE_OFF - - if 'overlay' in data: - overlay_data = data['overlay'] - overlay = overlay_data is not None - - if overlay: - termination = overlay_data['termination']['type'] - - if 'setting' in overlay_data: - cooling = overlay_data['setting']['mode'] == 'COOL' - fan_speed = overlay_data['setting']['fanSpeed'] - # If you set mode manualy to off, there will be an overlay # and a termination, but we want to see the mode "OFF" - self._overlay_mode = termination self._current_operation = termination - self._cooling = cooling - self._current_fan = fan_speed + + self._cooling = cooling + self._current_fan = fan_speed def _control_heating(self): """Send new target temperature to mytado.""" From f0293eeac22c2fa8cf29a1741ff7c1f420ce8a6b Mon Sep 17 00:00:00 2001 From: Russell Cloran Date: Sun, 23 Jul 2017 23:49:03 -0700 Subject: [PATCH 079/118] prometheus: Fix zwave battery level (#8615) --- homeassistant/components/prometheus.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/homeassistant/components/prometheus.py b/homeassistant/components/prometheus.py index 18a3a932d36..f244bcdd740 100644 --- a/homeassistant/components/prometheus.py +++ b/homeassistant/components/prometheus.py @@ -216,6 +216,9 @@ class Metrics: value = state_helper.state_as_number(state) metric.labels(**self._labels(state)).set(value) + def _handle_zwave(self, state): + self._battery(state) + class PrometheusView(HomeAssistantView): """Handle Prometheus requests.""" From b0b6026c68787e9b0a25bd4a177f6c3994e51064 Mon Sep 17 00:00:00 2001 From: Anton Lundin Date: Mon, 24 Jul 2017 08:51:07 +0200 Subject: [PATCH 080/118] ubus: Make multiple instances work again (#8571) Back in "ubus: Refresh session on Access denied (#8111)" I added the decorator _refresh_on_acccess_denied. Somehow that stopped multiple ubus trackers from working in parallel, and only the one first init'ed worked. Changing the order of the decorators fixes the issue but, I'm sorry to say I can't figure out why. There's some magic somewhere which I'm missing. Signed-off-by: Anton Lundin --- homeassistant/components/device_tracker/ubus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/device_tracker/ubus.py b/homeassistant/components/device_tracker/ubus.py index e3cef60c376..8d4cd1dcd73 100644 --- a/homeassistant/components/device_tracker/ubus.py +++ b/homeassistant/components/device_tracker/ubus.py @@ -115,8 +115,8 @@ class UbusDeviceScanner(DeviceScanner): return self.mac2name.get(device.upper(), None) - @Throttle(MIN_TIME_BETWEEN_SCANS) @_refresh_on_acccess_denied + @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the Luci router is up to date. From f3d9086ff4d2972a8839365db830841ff2e0e881 Mon Sep 17 00:00:00 2001 From: Jeff Wilson Date: Mon, 24 Jul 2017 02:53:03 -0400 Subject: [PATCH 081/118] Properly slugify switch.flux update service name (#8545) --- homeassistant/components/switch/flux.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/switch/flux.py b/homeassistant/components/switch/flux.py index dea4285e3a9..5613bcbb19e 100644 --- a/homeassistant/components/switch/flux.py +++ b/homeassistant/components/switch/flux.py @@ -15,6 +15,7 @@ from homeassistant.components.switch import DOMAIN, SwitchDevice from homeassistant.const import CONF_NAME, CONF_PLATFORM from homeassistant.helpers.event import track_time_change from homeassistant.helpers.sun import get_astral_event_date +from homeassistant.util import slugify from homeassistant.util.color import ( color_temperature_to_rgb, color_RGB_to_xy, color_temperature_kelvin_to_mired) @@ -111,7 +112,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Update lights.""" flux.flux_update() - hass.services.register(DOMAIN, name + '_update', update) + service_name = slugify("{} {}".format(name, 'update')) + hass.services.register(DOMAIN, service_name, update) class FluxSwitch(SwitchDevice): From a2abb4ae0a694389494792527e79e7b4c949d452 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 24 Jul 2017 00:11:58 -0700 Subject: [PATCH 082/118] Update frontend --- homeassistant/components/frontend/version.py | 6 +++--- .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 138190 -> 138831 bytes .../www_static/home-assistant-polymer | 2 +- .../www_static/panels/ha-panel-config.html | 2 +- .../www_static/panels/ha-panel-config.html.gz | Bin 15074 -> 15057 bytes .../www_static/panels/ha-panel-hassio.html | 2 +- .../www_static/panels/ha-panel-hassio.html.gz | Bin 409 -> 378 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2485 -> 2487 bytes 10 files changed, 8 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 6ab94fe5a78..ddfd8a33051 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -3,17 +3,17 @@ FINGERPRINTS = { "compatibility.js": "8e4c44b5f4288cc48ec1ba94a9bec812", "core.js": "d4a7cb8c80c62b536764e0e81385f6aa", - "frontend.html": "7bd9aa75b2602768e66cf7e20845d7c4", + "frontend.html": "d0142106cf282596062e5b2060128f81", "mdi.html": "e91f61a039ed0a9936e7ee5360da3870", "micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a", "panels/ha-panel-automation.html": "72a5c1856cece8d9246328e84185ab0b", - "panels/ha-panel-config.html": "c0e043028cfa75d6d4dc5e0de0bb6dc1", + "panels/ha-panel-config.html": "5e2df66aa534c4dadd08c60c361f5d45", "panels/ha-panel-dev-event.html": "4886c821235492b1b92739b580d21c61", "panels/ha-panel-dev-info.html": "24e888ec7a8acd0c395b34396e9001bc", "panels/ha-panel-dev-service.html": "ac2c50e486927dc4443e93d79f08c06e", "panels/ha-panel-dev-state.html": "8f1a27c04db6329d31cfcc7d0d6a0869", "panels/ha-panel-dev-template.html": "82cd543177c417e5c6612e07df851e6b", - "panels/ha-panel-hassio.html": "96d563215cf7bf7b0eeaf8625bafa4ef", + "panels/ha-panel-hassio.html": "262d31efd9add719e0325da5cf79a096", "panels/ha-panel-history.html": "35177e2046c9a4191c8f51f8160255ce", "panels/ha-panel-iframe.html": "238189f21e670b6dcfac937e5ebd7d3b", "panels/ha-panel-kiosk.html": "2ac2df41bd447600692a0054892fc094", diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index 3205a1d7d4f..ad1e407587e 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -2,4 +2,4 @@ this._useContent&&u.Logical.saveChildNodes(this)},_setupRoot:function(){this._useContent&&(this._createLocalRoot(),this.dataHost||l(u.Logical.getChildNodes(this)))},_createLocalRoot:function(){this.shadyRoot=this.root,this.shadyRoot._distributionClean=!1,this.shadyRoot._hasDistributed=!1,this.shadyRoot._isShadyRoot=!0,this.shadyRoot._dirtyRoots=[];var e=this.shadyRoot._insertionPoints=!this._notes||this._notes._hasContent?this.shadyRoot.querySelectorAll("content"):[];u.Logical.saveChildNodes(this.shadyRoot);for(var t,o=0;o0?~setTimeout(e,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 +return performance.now()};else var t=function(){return Date.now()};var e=function(t,e,i){this.target=t,this.currentTime=e,this.timelineTime=i,this.type="cancel",this.bubbles=!1,this.cancelable=!1,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){}}(0,e),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 baceb29a98504762bb696a9090a16641c8b8df42..055f78334dc5f54ff652fc6261ecc9fc4edd133a 100644 GIT binary patch delta 27533 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 Wb4@m5dC8Ce%!W#p8Ebnv7#RRD-{uqm delta 26886 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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 c7be840a9d7..0c428134dfb 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit c7be840a9d73b6a32a0d74b1a5c0fb4475018d75 +Subproject commit 0c428134dfb6374b4a120cb729396242b4c2f2d7 diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-config.html b/homeassistant/components/frontend/www_static/panels/ha-panel-config.html index e54ba31fb3e..9ba6338ce00 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-config.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-config.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-config.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-config.html.gz index a0745b91349ec77b3bb8846abb57ad2bba6a624f..2364c355d66f65be42c949cf3d6fdbd309d9f248 100644 GIT binary patch delta 13870 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 diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.html b/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.html index 2ec3ee876b9..f339403019b 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.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-hassio.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-hassio.html.gz index 03b8a09f320d02b2f305c7298c4a974c64d689d7..6a1c2905cf0087ed1d383c04a1cd8ff53c21f228 100644 GIT binary patch literal 378 zcmb2|=3oE;Cg#+jgIRYB1pbP;E|1-C{fSu5^$VBU_O`HG`nE|YHR-Gpt7r0(Lb1m` z?rY!l-F9Je+PyuJ_oRIn-@Li)BFCy+8KVwA=Z+KAKR+L@tyI6gEUH_7$+2yLPrTf- zHfZ$R^5#wDm&;wL=;qvc_C*zUPp)v~mK$A=>LB z)u-_Fh+Ez}{n&8-^2s7{P7A! z^y_4n@`GRQ*iDp`Z9AKi^mqQjMf_Ki6Ph>9GYYfcwfJ}SNtjyO^? zLATK<)ZgaYkCPS5)(N%6*5_FboRE55xDBVS=581Q3>)RT9Z<&9R>v2_`;S#14vDjkCzPXAUO}dH|)E`Zl lvu~zHqWbpFW%IVb+aopE@#=0{Kib8uaP%;;^_@ccgr}N8n#M!G^jlXUN#xcqk6 z#$7)>n|3Eu<;kDu<2(E+De3S0gNyjDBqua)+?TTE-@h-?)_P)zU(=PkA9Sx?V4ffr z9AEL~9TWgY?YA5#8Z+f*gZxF%b(`|-!~4T&`k40^t^m#y5u!gW>q?9{4t<8 diff --git a/homeassistant/components/frontend/www_static/service_worker.js b/homeassistant/components/frontend/www_static/service_worker.js index 62d99bab65c..a73aff72274 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=[["/","0db8ddbf9b3ec817eebadc6866a9499d"],["/frontend/panels/dev-event-4886c821235492b1b92739b580d21c61.html","0f16df49a7d965ddc1fd55f7bd3ffd3f"],["/frontend/panels/dev-info-24e888ec7a8acd0c395b34396e9001bc.html","7bb116813e8dbab7bcfabdf4de3ec83f"],["/frontend/panels/dev-service-ac2c50e486927dc4443e93d79f08c06e.html","1daf8c159d2fab036f7094b0e737f1a0"],["/frontend/panels/dev-state-8f1a27c04db6329d31cfcc7d0d6a0869.html","002ea95ab67f5c06f9112008a81e571b"],["/frontend/panels/dev-template-82cd543177c417e5c6612e07df851e6b.html","81c4dbc540739dcf49c351cf565db71b"],["/frontend/panels/map-b4923812c695dd8a69ad3da380ffe7b4.html","e88c1c3fc6d3dd0db561ce0a1f5beaf5"],["/static/compatibility-8e4c44b5f4288cc48ec1ba94a9bec812.js","4704a985ad259e324c3d8a0a40f6d937"],["/static/core-d4a7cb8c80c62b536764e0e81385f6aa.js","37e34ec6aa0fa155c7d50e2883be1ead"],["/static/frontend-7bd9aa75b2602768e66cf7e20845d7c4.html","054d60e22570068f7b2f43cb893d40f7"],["/static/mdi-e91f61a039ed0a9936e7ee5360da3870.html","5e587bc82719b740a4f0798722a83aee"],["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","32b5a9b7ada86304bec6b43d3f2194f0"]],cacheName="sw-precache-v3--"+(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()},cleanResponse=function(e){return e.redirected?("body"in e?Promise.resolve(e.body):e.blob()).then(function(t){return new Response(t,{headers:e.headers,status:e.status,statusText:e.statusText})}):Promise.resolve(e)},createCacheKey=function(e,t,n,a){var c=new URL(e);return a&&c.pathname.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)){var a=new Request(n,{credentials:"same-origin"});return fetch(a).then(function(t){if(!t.ok)throw new Error("Request for "+n+" returned a response with status "+t.status);return cleanResponse(t).then(function(t){return e.put(n,t)})})}}))})}).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);t||(n=addDirectoryIndex(n,"index.html"),t=urlsToCacheKeys.has(n));!t&&"navigate"===e.request.mode&&isPathWhitelisted(["^((?!(static|api|local|service_worker.js|manifest.json)).)*$"],e.request.url)&&(n=new URL("/",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)&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var n,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 gQ}5WB@7?A Date: Mon, 24 Jul 2017 14:22:12 +0100 Subject: [PATCH 083/118] added onvif camera fix for non-virtual env installations (#8592) * added fix for non-virtual env installations * fixed new line at end of file * moved import os to top of file --- homeassistant/components/camera/onvif.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/camera/onvif.py b/homeassistant/components/camera/onvif.py index f1c94f79c0b..711eb75a744 100644 --- a/homeassistant/components/camera/onvif.py +++ b/homeassistant/components/camera/onvif.py @@ -6,6 +6,7 @@ https://home-assistant.io/components/camera.onvif/ """ import asyncio import logging +import os import voluptuous as vol @@ -54,6 +55,7 @@ class ONVIFCamera(Camera): def __init__(self, hass, config): """Initialize a ONVIF camera.""" from onvif import ONVIFService + import onvif super().__init__() self._name = config.get(CONF_NAME) @@ -63,7 +65,7 @@ class ONVIFCamera(Camera): config.get(CONF_HOST), config.get(CONF_PORT)), config.get(CONF_USERNAME), config.get(CONF_PASSWORD), - '{}/deps/onvif/wsdl/media.wsdl'.format(hass.config.config_dir) + '{}/wsdl/media.wsdl'.format(os.path.dirname(onvif.__file__)) ) self._input = media.GetStreamUri().Uri _LOGGER.debug("ONVIF Camera Using the following URL for %s: %s", From f86bd155801a704c9bb6a7080b603a762ce526d6 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 24 Jul 2017 16:45:02 +0200 Subject: [PATCH 084/118] Cleanup old device_tracker stuff (#8627) * Cleanup old device_tracker stuff * Fix lint --- .../components/device_tracker/actiontec.py | 26 +- .../components/device_tracker/aruba.py | 19 +- .../components/device_tracker/asuswrt.py | 31 +- .../device_tracker/bt_home_hub_5.py | 38 +-- .../components/device_tracker/cisco_ios.py | 5 - .../components/device_tracker/ddwrt.py | 92 +++-- .../components/device_tracker/fritz.py | 5 - .../components/device_tracker/linksys_ap.py | 28 +- .../device_tracker/linksys_smart.py | 78 ++--- .../components/device_tracker/luci.py | 82 ++--- .../components/device_tracker/mikrotik.py | 90 +++-- .../components/device_tracker/netgear.py | 19 +- .../components/device_tracker/nmap_tracker.py | 6 +- .../components/device_tracker/sky_hub.py | 38 +-- .../components/device_tracker/snmp.py | 20 +- .../components/device_tracker/swisscom.py | 26 +- .../components/device_tracker/thomson.py | 28 +- .../components/device_tracker/tomato.py | 75 ++-- .../components/device_tracker/tplink.py | 322 +++++++++--------- .../components/device_tracker/ubus.py | 82 ++--- .../components/device_tracker/volvooncall.py | 3 +- .../components/device_tracker/xiaomi.py | 44 +-- 22 files changed, 478 insertions(+), 679 deletions(-) diff --git a/homeassistant/components/device_tracker/actiontec.py b/homeassistant/components/device_tracker/actiontec.py index 882df575385..64e1a60ad08 100644 --- a/homeassistant/components/device_tracker/actiontec.py +++ b/homeassistant/components/device_tracker/actiontec.py @@ -7,9 +7,7 @@ https://home-assistant.io/components/device_tracker.actiontec/ import logging import re import telnetlib -import threading from collections import namedtuple -from datetime import timedelta import voluptuous as vol import homeassistant.helpers.config_validation as cv @@ -17,9 +15,6 @@ import homeassistant.util.dt as dt_util from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle - -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) _LOGGER = logging.getLogger(__name__) @@ -54,7 +49,6 @@ class ActiontecDeviceScanner(DeviceScanner): self.host = config[CONF_HOST] self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] - self.lock = threading.Lock() self.last_results = [] data = self.get_actiontec_data() self.success_init = data is not None @@ -74,7 +68,6 @@ class ActiontecDeviceScanner(DeviceScanner): return client.ip return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the router is up to date. @@ -84,16 +77,15 @@ class ActiontecDeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - now = dt_util.now() - actiontec_data = self.get_actiontec_data() - if not actiontec_data: - return False - self.last_results = [Device(data['mac'], name, now) - for name, data in actiontec_data.items() - if data['timevalid'] > -60] - _LOGGER.info("Scan successful") - return True + now = dt_util.now() + actiontec_data = self.get_actiontec_data() + if not actiontec_data: + return False + self.last_results = [Device(data['mac'], name, now) + for name, data in actiontec_data.items() + if data['timevalid'] > -60] + _LOGGER.info("Scan successful") + return True def get_actiontec_data(self): """Retrieve data from Actiontec MI424WR and return parsed result.""" diff --git a/homeassistant/components/device_tracker/aruba.py b/homeassistant/components/device_tracker/aruba.py index bfb1588b323..cef5eabd901 100644 --- a/homeassistant/components/device_tracker/aruba.py +++ b/homeassistant/components/device_tracker/aruba.py @@ -6,8 +6,6 @@ https://home-assistant.io/components/device_tracker.aruba/ """ import logging import re -import threading -from datetime import timedelta import voluptuous as vol @@ -15,14 +13,11 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle _LOGGER = logging.getLogger(__name__) REQUIREMENTS = ['pexpect==4.0.1'] -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) - _DEVICES_REGEX = re.compile( r'(?P([^\s]+))\s+' + r'(?P([0-9]{1,3}[\.]){3}[0-9]{1,3})\s+' + @@ -52,8 +47,6 @@ class ArubaDeviceScanner(DeviceScanner): self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] - self.lock = threading.Lock() - self.last_results = {} # Test the router is accessible. @@ -74,7 +67,6 @@ class ArubaDeviceScanner(DeviceScanner): return client['name'] return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the Aruba Access Point is up to date. @@ -83,13 +75,12 @@ class ArubaDeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - data = self.get_aruba_data() - if not data: - return False + data = self.get_aruba_data() + if not data: + return False - self.last_results = data.values() - return True + self.last_results = data.values() + return True def get_aruba_data(self): """Retrieve data from Aruba Access Point and return parsed result.""" diff --git a/homeassistant/components/device_tracker/asuswrt.py b/homeassistant/components/device_tracker/asuswrt.py index b28d16cc4a1..9b214441ac9 100644 --- a/homeassistant/components/device_tracker/asuswrt.py +++ b/homeassistant/components/device_tracker/asuswrt.py @@ -8,9 +8,7 @@ import logging import re import socket import telnetlib -import threading from collections import namedtuple -from datetime import timedelta import voluptuous as vol @@ -18,7 +16,6 @@ from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import ( CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_PORT) -from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['pexpect==4.0.1'] @@ -32,8 +29,6 @@ CONF_SSH_KEY = 'ssh_key' DEFAULT_SSH_PORT = 22 -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) - SECRET_GROUP = 'Password or SSH Key' PLATFORM_SCHEMA = vol.All( @@ -123,8 +118,6 @@ class AsusWrtDeviceScanner(DeviceScanner): self.password, self.mode == "ap") - self.lock = threading.Lock() - self.last_results = {} # Test the router is accessible. @@ -145,7 +138,6 @@ class AsusWrtDeviceScanner(DeviceScanner): return client['host'] return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the ASUSWRT router is up to date. @@ -154,19 +146,18 @@ class AsusWrtDeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - _LOGGER.info('Checking Devices') - data = self.get_asuswrt_data() - if not data: - return False + _LOGGER.info('Checking Devices') + data = self.get_asuswrt_data() + if not data: + return False - active_clients = [client for client in data.values() if - client['status'] == 'REACHABLE' or - client['status'] == 'DELAY' or - client['status'] == 'STALE' or - client['status'] == 'IN_ASSOCLIST'] - self.last_results = active_clients - return True + active_clients = [client for client in data.values() if + client['status'] == 'REACHABLE' or + client['status'] == 'DELAY' or + client['status'] == 'STALE' or + client['status'] == 'IN_ASSOCLIST'] + self.last_results = active_clients + return True def get_asuswrt_data(self): """Retrieve data from ASUSWRT and return parsed result.""" diff --git a/homeassistant/components/device_tracker/bt_home_hub_5.py b/homeassistant/components/device_tracker/bt_home_hub_5.py index 5c1a14b446b..a3b5bcac77c 100644 --- a/homeassistant/components/device_tracker/bt_home_hub_5.py +++ b/homeassistant/components/device_tracker/bt_home_hub_5.py @@ -6,8 +6,6 @@ https://home-assistant.io/components/device_tracker.bt_home_hub_5/ """ import logging import re -import threading -from datetime import timedelta import xml.etree.ElementTree as ET import json from urllib.parse import unquote @@ -19,13 +17,10 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST -from homeassistant.util import Throttle _LOGGER = logging.getLogger(__name__) _MAC_REGEX = re.compile(r'(([0-9A-Fa-f]{1,2}\:){5}[0-9A-Fa-f]{1,2})') -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string }) @@ -46,11 +41,7 @@ class BTHomeHub5DeviceScanner(DeviceScanner): """Initialise the scanner.""" _LOGGER.info("Initialising BT Home Hub 5") self.host = config.get(CONF_HOST, '192.168.1.254') - - self.lock = threading.Lock() - self.last_results = {} - self.url = 'http://{}/nonAuth/home_status.xml'.format(self.host) # Test the router is accessible @@ -65,17 +56,15 @@ class BTHomeHub5DeviceScanner(DeviceScanner): def get_device_name(self, device): """Return the name of the given device or None if we don't know.""" - with self.lock: - # If not initialised and not already scanned and not found. - if device not in self.last_results: - self._update_info() + # If not initialised and not already scanned and not found. + if device not in self.last_results: + self._update_info() - if not self.last_results: - return None + if not self.last_results: + return None - return self.last_results.get(device) + return self.last_results.get(device) - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the BT Home Hub 5 is up to date. @@ -84,18 +73,17 @@ class BTHomeHub5DeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - _LOGGER.info("Scanning") + _LOGGER.info("Scanning") - data = _get_homehub_data(self.url) + data = _get_homehub_data(self.url) - if not data: - _LOGGER.warning("Error scanning devices") - return False + if not data: + _LOGGER.warning("Error scanning devices") + return False - self.last_results = data + self.last_results = data - return True + return True def _get_homehub_data(url): diff --git a/homeassistant/components/device_tracker/cisco_ios.py b/homeassistant/components/device_tracker/cisco_ios.py index 99ed06de486..0978ba99593 100644 --- a/homeassistant/components/device_tracker/cisco_ios.py +++ b/homeassistant/components/device_tracker/cisco_ios.py @@ -5,7 +5,6 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/device_tracker.cisco_ios/ """ import logging -from datetime import timedelta import voluptuous as vol @@ -14,9 +13,6 @@ from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, \ CONF_PORT -from homeassistant.util import Throttle - -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) _LOGGER = logging.getLogger(__name__) @@ -65,7 +61,6 @@ class CiscoDeviceScanner(DeviceScanner): return self.last_results - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """ Ensure the information from the Cisco router is up to date. diff --git a/homeassistant/components/device_tracker/ddwrt.py b/homeassistant/components/device_tracker/ddwrt.py index 4f1efcdb27c..3d36a1b428c 100644 --- a/homeassistant/components/device_tracker/ddwrt.py +++ b/homeassistant/components/device_tracker/ddwrt.py @@ -6,8 +6,6 @@ https://home-assistant.io/components/device_tracker.ddwrt/ """ import logging import re -import threading -from datetime import timedelta import requests import voluptuous as vol @@ -16,9 +14,6 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle - -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) _LOGGER = logging.getLogger(__name__) @@ -50,8 +45,6 @@ class DdWrtDeviceScanner(DeviceScanner): self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] - self.lock = threading.Lock() - self.last_results = {} self.mac2name = {} @@ -69,68 +62,65 @@ class DdWrtDeviceScanner(DeviceScanner): def get_device_name(self, device): """Return the name of the given device or None if we don't know.""" - with self.lock: - # If not initialised and not already scanned and not found. - if device not in self.mac2name: - url = 'http://{}/Status_Lan.live.asp'.format(self.host) - data = self.get_ddwrt_data(url) + # If not initialised and not already scanned and not found. + if device not in self.mac2name: + url = 'http://{}/Status_Lan.live.asp'.format(self.host) + data = self.get_ddwrt_data(url) - if not data: - return None + if not data: + return None - dhcp_leases = data.get('dhcp_leases', None) + dhcp_leases = data.get('dhcp_leases', None) - if not dhcp_leases: - return None + if not dhcp_leases: + return None - # Remove leading and trailing quotes and spaces - cleaned_str = dhcp_leases.replace( - "\"", "").replace("\'", "").replace(" ", "") - elements = cleaned_str.split(',') - num_clients = int(len(elements) / 5) - self.mac2name = {} - for idx in range(0, num_clients): - # The data is a single array - # every 5 elements represents one host, the MAC - # is the third element and the name is the first. - mac_index = (idx * 5) + 2 - if mac_index < len(elements): - mac = elements[mac_index] - self.mac2name[mac] = elements[idx * 5] + # Remove leading and trailing quotes and spaces + cleaned_str = dhcp_leases.replace( + "\"", "").replace("\'", "").replace(" ", "") + elements = cleaned_str.split(',') + num_clients = int(len(elements) / 5) + self.mac2name = {} + for idx in range(0, num_clients): + # The data is a single array + # every 5 elements represents one host, the MAC + # is the third element and the name is the first. + mac_index = (idx * 5) + 2 + if mac_index < len(elements): + mac = elements[mac_index] + self.mac2name[mac] = elements[idx * 5] - return self.mac2name.get(device) + return self.mac2name.get(device) - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the DD-WRT router is up to date. Return boolean if scanning successful. """ - with self.lock: - _LOGGER.info("Checking ARP") + _LOGGER.info("Checking ARP") - url = 'http://{}/Status_Wireless.live.asp'.format(self.host) - data = self.get_ddwrt_data(url) + url = 'http://{}/Status_Wireless.live.asp'.format(self.host) + data = self.get_ddwrt_data(url) - if not data: - return False + if not data: + return False - self.last_results = [] + self.last_results = [] - active_clients = data.get('active_wireless', None) - if not active_clients: - return False + active_clients = data.get('active_wireless', None) + if not active_clients: + return False - # The DD-WRT UI uses its own data format and then - # regex's out values so this is done here too - # Remove leading and trailing single quotes. - clean_str = active_clients.strip().strip("'") - elements = clean_str.split("','") + # The DD-WRT UI uses its own data format and then + # regex's out values so this is done here too + # Remove leading and trailing single quotes. + clean_str = active_clients.strip().strip("'") + elements = clean_str.split("','") - self.last_results.extend(item for item in elements - if _MAC_REGEX.match(item)) + self.last_results.extend(item for item in elements + if _MAC_REGEX.match(item)) - return True + return True def get_ddwrt_data(self, url): """Retrieve data from DD-WRT and return parsed result.""" diff --git a/homeassistant/components/device_tracker/fritz.py b/homeassistant/components/device_tracker/fritz.py index 25de0a35c82..5210329179f 100644 --- a/homeassistant/components/device_tracker/fritz.py +++ b/homeassistant/components/device_tracker/fritz.py @@ -5,7 +5,6 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/device_tracker.fritz/ """ import logging -from datetime import timedelta import voluptuous as vol @@ -13,12 +12,9 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle REQUIREMENTS = ['fritzconnection==0.6.3'] -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) - _LOGGER = logging.getLogger(__name__) CONF_DEFAULT_IP = '169.254.1.1' # This IP is valid for all FRITZ!Box routers. @@ -88,7 +84,6 @@ class FritzBoxScanner(DeviceScanner): return None return ret - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Retrieve latest information from the FRITZ!Box.""" if not self.success_init: diff --git a/homeassistant/components/device_tracker/linksys_ap.py b/homeassistant/components/device_tracker/linksys_ap.py index 01f97eb6e42..196235f32f4 100644 --- a/homeassistant/components/device_tracker/linksys_ap.py +++ b/homeassistant/components/device_tracker/linksys_ap.py @@ -6,8 +6,6 @@ https://home-assistant.io/components/device_tracker.linksys_ap/ """ import base64 import logging -import threading -from datetime import timedelta import requests import voluptuous as vol @@ -16,9 +14,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import DOMAIN, PLATFORM_SCHEMA from homeassistant.const import ( CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_VERIFY_SSL) -from homeassistant.util import Throttle -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) INTERFACES = 2 DEFAULT_TIMEOUT = 10 @@ -51,8 +47,6 @@ class LinksysAPDeviceScanner(object): self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] self.verify_ssl = config[CONF_VERIFY_SSL] - - self.lock = threading.Lock() self.last_results = [] # Check if the access point is accessible @@ -76,24 +70,22 @@ class LinksysAPDeviceScanner(object): """ return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Check for connected devices.""" from bs4 import BeautifulSoup as BS - with self.lock: - _LOGGER.info("Checking Linksys AP") + _LOGGER.info("Checking Linksys AP") - self.last_results = [] - for interface in range(INTERFACES): - request = self._make_request(interface) - self.last_results.extend( - [x.find_all('td')[1].text - for x in BS(request.content, "html.parser") - .find_all(class_='section-row')] - ) + self.last_results = [] + for interface in range(INTERFACES): + request = self._make_request(interface) + self.last_results.extend( + [x.find_all('td')[1].text + for x in BS(request.content, "html.parser") + .find_all(class_='section-row')] + ) - return True + return True def _make_request(self, unit=0): # No, the '&&' is not a typo - this is expected by the web interface. diff --git a/homeassistant/components/device_tracker/linksys_smart.py b/homeassistant/components/device_tracker/linksys_smart.py index e71502ba5ee..4bcbb600b8b 100644 --- a/homeassistant/components/device_tracker/linksys_smart.py +++ b/homeassistant/components/device_tracker/linksys_smart.py @@ -1,7 +1,5 @@ """Support for Linksys Smart Wifi routers.""" import logging -import threading -from datetime import timedelta import requests import voluptuous as vol @@ -10,9 +8,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST -from homeassistant.util import Throttle -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) DEFAULT_TIMEOUT = 10 _LOGGER = logging.getLogger(__name__) @@ -36,8 +32,6 @@ class LinksysSmartWifiDeviceScanner(DeviceScanner): def __init__(self, config): """Initialize the scanner.""" self.host = config[CONF_HOST] - - self.lock = threading.Lock() self.last_results = {} # Check if the access point is accessible @@ -55,48 +49,46 @@ class LinksysSmartWifiDeviceScanner(DeviceScanner): """Return the name (if known) of the device.""" return self.last_results.get(mac) - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Check for connected devices.""" - with self.lock: - _LOGGER.info("Checking Linksys Smart Wifi") + _LOGGER.info("Checking Linksys Smart Wifi") - self.last_results = {} - response = self._make_request() - if response.status_code != 200: - _LOGGER.error( - "Got HTTP status code %d when getting device list", - response.status_code) - return False - try: - data = response.json() - result = data["responses"][0] - devices = result["output"]["devices"] - for device in devices: - macs = device["knownMACAddresses"] - if not macs: - _LOGGER.warning( - "Skipping device without known MAC address") - continue - mac = macs[-1] - connections = device["connections"] - if not connections: - _LOGGER.debug("Device %s is not connected", mac) - continue + self.last_results = {} + response = self._make_request() + if response.status_code != 200: + _LOGGER.error( + "Got HTTP status code %d when getting device list", + response.status_code) + return False + try: + data = response.json() + result = data["responses"][0] + devices = result["output"]["devices"] + for device in devices: + macs = device["knownMACAddresses"] + if not macs: + _LOGGER.warning( + "Skipping device without known MAC address") + continue + mac = macs[-1] + connections = device["connections"] + if not connections: + _LOGGER.debug("Device %s is not connected", mac) + continue - name = None - for prop in device["properties"]: - if prop["name"] == "userDeviceName": - name = prop["value"] - if not name: - name = device.get("friendlyName", device["deviceID"]) + name = None + for prop in device["properties"]: + if prop["name"] == "userDeviceName": + name = prop["value"] + if not name: + name = device.get("friendlyName", device["deviceID"]) - _LOGGER.debug("Device %s is connected", mac) - self.last_results[mac] = name - except (KeyError, IndexError): - _LOGGER.exception("Router returned unexpected response") - return False - return True + _LOGGER.debug("Device %s is connected", mac) + self.last_results[mac] = name + except (KeyError, IndexError): + _LOGGER.exception("Router returned unexpected response") + return False + return True def _make_request(self): # Weirdly enough, this doesn't seem to require authentication diff --git a/homeassistant/components/device_tracker/luci.py b/homeassistant/components/device_tracker/luci.py index 24af81b281e..a4b826a009f 100644 --- a/homeassistant/components/device_tracker/luci.py +++ b/homeassistant/components/device_tracker/luci.py @@ -7,8 +7,6 @@ https://home-assistant.io/components/device_tracker.luci/ import json import logging import re -import threading -from datetime import timedelta import requests import voluptuous as vol @@ -18,9 +16,6 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle - -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) _LOGGER = logging.getLogger(__name__) @@ -55,12 +50,8 @@ class LuciDeviceScanner(DeviceScanner): self.parse_api_pattern = re.compile(r"(?P\w*) = (?P.*);") - self.lock = threading.Lock() - self.last_results = {} - self.refresh_token() - self.mac2name = None self.success_init = self.token is not None @@ -75,24 +66,22 @@ class LuciDeviceScanner(DeviceScanner): def get_device_name(self, device): """Return the name of the given device or None if we don't know.""" - with self.lock: - if self.mac2name is None: - url = 'http://{}/cgi-bin/luci/rpc/uci'.format(self.host) - result = _req_json_rpc(url, 'get_all', 'dhcp', - params={'auth': self.token}) - if result: - hosts = [x for x in result.values() - if x['.type'] == 'host' and - 'mac' in x and 'name' in x] - mac2name_list = [ - (x['mac'].upper(), x['name']) for x in hosts] - self.mac2name = dict(mac2name_list) - else: - # Error, handled in the _req_json_rpc - return - return self.mac2name.get(device.upper(), None) + if self.mac2name is None: + url = 'http://{}/cgi-bin/luci/rpc/uci'.format(self.host) + result = _req_json_rpc(url, 'get_all', 'dhcp', + params={'auth': self.token}) + if result: + hosts = [x for x in result.values() + if x['.type'] == 'host' and + 'mac' in x and 'name' in x] + mac2name_list = [ + (x['mac'].upper(), x['name']) for x in hosts] + self.mac2name = dict(mac2name_list) + else: + # Error, handled in the _req_json_rpc + return + return self.mac2name.get(device.upper(), None) - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the Luci router is up to date. @@ -101,31 +90,30 @@ class LuciDeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - _LOGGER.info("Checking ARP") + _LOGGER.info("Checking ARP") - url = 'http://{}/cgi-bin/luci/rpc/sys'.format(self.host) - - try: - result = _req_json_rpc(url, 'net.arptable', - params={'auth': self.token}) - except InvalidLuciTokenError: - _LOGGER.info("Refreshing token") - self.refresh_token() - return False - - if result: - self.last_results = [] - for device_entry in result: - # Check if the Flags for each device contain - # NUD_REACHABLE and if so, add it to last_results - if int(device_entry['Flags'], 16) & 0x2: - self.last_results.append(device_entry['HW address']) - - return True + url = 'http://{}/cgi-bin/luci/rpc/sys'.format(self.host) + try: + result = _req_json_rpc(url, 'net.arptable', + params={'auth': self.token}) + except InvalidLuciTokenError: + _LOGGER.info("Refreshing token") + self.refresh_token() return False + if result: + self.last_results = [] + for device_entry in result: + # Check if the Flags for each device contain + # NUD_REACHABLE and if so, add it to last_results + if int(device_entry['Flags'], 16) & 0x2: + self.last_results.append(device_entry['HW address']) + + return True + + return False + def _req_json_rpc(url, method, *args, **kwargs): """Perform one JSON RPC operation.""" diff --git a/homeassistant/components/device_tracker/mikrotik.py b/homeassistant/components/device_tracker/mikrotik.py index fc1918f08cc..4e43b6ac10d 100644 --- a/homeassistant/components/device_tracker/mikrotik.py +++ b/homeassistant/components/device_tracker/mikrotik.py @@ -5,25 +5,17 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/device_tracker.mikrotik/ """ import logging -import threading -from datetime import timedelta import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) -from homeassistant.const import (CONF_HOST, - CONF_PASSWORD, - CONF_USERNAME, - CONF_PORT) -from homeassistant.util import Throttle +from homeassistant.const import ( + CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_PORT) REQUIREMENTS = ['librouteros==1.0.2'] -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) - MTK_DEFAULT_API_PORT = '8728' _LOGGER = logging.getLogger(__name__) @@ -54,12 +46,9 @@ class MikrotikScanner(DeviceScanner): self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] - self.lock = threading.Lock() - self.connected = False self.success_init = False self.client = None - self.wireless_exist = None self.success_init = self.connect_to_device() @@ -118,51 +107,48 @@ class MikrotikScanner(DeviceScanner): def get_device_name(self, mac): """Return the name of the given device or None if we don't know.""" - with self.lock: - return self.last_results.get(mac) + return self.last_results.get(mac) - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Retrieve latest information from the Mikrotik box.""" - with self.lock: - if self.wireless_exist: - devices_tracker = 'wireless' - else: - devices_tracker = 'ip' + if self.wireless_exist: + devices_tracker = 'wireless' + else: + devices_tracker = 'ip' - _LOGGER.info( - "Loading %s devices from Mikrotik (%s) ...", - devices_tracker, - self.host + _LOGGER.info( + "Loading %s devices from Mikrotik (%s) ...", + devices_tracker, + self.host + ) + + device_names = self.client(cmd='/ip/dhcp-server/lease/getall') + if self.wireless_exist: + devices = self.client( + cmd='/interface/wireless/registration-table/getall' ) + else: + devices = device_names - device_names = self.client(cmd='/ip/dhcp-server/lease/getall') - if self.wireless_exist: - devices = self.client( - cmd='/interface/wireless/registration-table/getall' - ) - else: - devices = device_names + if device_names is None and devices is None: + return False - if device_names is None and devices is None: - return False + mac_names = {device.get('mac-address'): device.get('host-name') + for device in device_names + if device.get('mac-address')} - mac_names = {device.get('mac-address'): device.get('host-name') - for device in device_names - if device.get('mac-address')} + if self.wireless_exist: + self.last_results = { + device.get('mac-address'): + mac_names.get(device.get('mac-address')) + for device in devices + } + else: + self.last_results = { + device.get('mac-address'): + mac_names.get(device.get('mac-address')) + for device in device_names + if device.get('active-address') + } - if self.wireless_exist: - self.last_results = { - device.get('mac-address'): - mac_names.get(device.get('mac-address')) - for device in devices - } - else: - self.last_results = { - device.get('mac-address'): - mac_names.get(device.get('mac-address')) - for device in device_names - if device.get('active-address') - } - - return True + return True diff --git a/homeassistant/components/device_tracker/netgear.py b/homeassistant/components/device_tracker/netgear.py index b3ec442198e..d2b8bc274ca 100644 --- a/homeassistant/components/device_tracker/netgear.py +++ b/homeassistant/components/device_tracker/netgear.py @@ -5,8 +5,6 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/device_tracker.netgear/ """ import logging -import threading -from datetime import timedelta import voluptuous as vol @@ -15,14 +13,11 @@ from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import ( CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_PORT) -from homeassistant.util import Throttle REQUIREMENTS = ['pynetgear==0.3.3'] _LOGGER = logging.getLogger(__name__) -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) - DEFAULT_HOST = 'routerlogin.net' DEFAULT_USER = 'admin' DEFAULT_PORT = 5000 @@ -56,8 +51,6 @@ class NetgearDeviceScanner(DeviceScanner): import pynetgear self.last_results = [] - self.lock = threading.Lock() - self._api = pynetgear.Netgear(password, host, username, port) _LOGGER.info("Logging in") @@ -85,7 +78,6 @@ class NetgearDeviceScanner(DeviceScanner): except StopIteration: return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Retrieve latest information from the Netgear router. @@ -94,12 +86,11 @@ class NetgearDeviceScanner(DeviceScanner): if not self.success_init: return - with self.lock: - _LOGGER.info("Scanning") + _LOGGER.info("Scanning") - results = self._api.get_attached_devices() + results = self._api.get_attached_devices() - if results is None: - _LOGGER.warning("Error scanning devices") + if results is None: + _LOGGER.warning("Error scanning devices") - self.last_results = results or [] + self.last_results = results or [] diff --git a/homeassistant/components/device_tracker/nmap_tracker.py b/homeassistant/components/device_tracker/nmap_tracker.py index 8a845adf0b8..e9d70142ad1 100644 --- a/homeassistant/components/device_tracker/nmap_tracker.py +++ b/homeassistant/components/device_tracker/nmap_tracker.py @@ -4,11 +4,11 @@ Support for scanning a network with nmap. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/device_tracker.nmap_tracker/ """ +from datetime import timedelta import logging import re import subprocess from collections import namedtuple -from datetime import timedelta import voluptuous as vol @@ -17,7 +17,6 @@ import homeassistant.util.dt as dt_util from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOSTS -from homeassistant.util import Throttle REQUIREMENTS = ['python-nmap==0.6.1'] @@ -29,8 +28,6 @@ CONF_HOME_INTERVAL = 'home_interval' CONF_OPTIONS = 'scan_options' DEFAULT_OPTIONS = '-F --host-timeout 5s' -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOSTS): cv.ensure_list, @@ -97,7 +94,6 @@ class NmapDeviceScanner(DeviceScanner): return filter_named[0] return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Scan the network for devices. diff --git a/homeassistant/components/device_tracker/sky_hub.py b/homeassistant/components/device_tracker/sky_hub.py index ef58c50991c..c48c9bd029b 100644 --- a/homeassistant/components/device_tracker/sky_hub.py +++ b/homeassistant/components/device_tracker/sky_hub.py @@ -6,8 +6,6 @@ https://home-assistant.io/components/device_tracker.sky_hub/ """ import logging import re -import threading -from datetime import timedelta import requests import voluptuous as vol @@ -16,13 +14,10 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST -from homeassistant.util import Throttle _LOGGER = logging.getLogger(__name__) _MAC_REGEX = re.compile(r'(([0-9A-Fa-f]{1,2}\:){5}[0-9A-Fa-f]{1,2})') -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string }) @@ -43,11 +38,7 @@ class SkyHubDeviceScanner(DeviceScanner): """Initialise the scanner.""" _LOGGER.info("Initialising Sky Hub") self.host = config.get(CONF_HOST, '192.168.1.254') - - self.lock = threading.Lock() - self.last_results = {} - self.url = 'http://{}/'.format(self.host) # Test the router is accessible @@ -62,17 +53,15 @@ class SkyHubDeviceScanner(DeviceScanner): def get_device_name(self, device): """Return the name of the given device or None if we don't know.""" - with self.lock: - # If not initialised and not already scanned and not found. - if device not in self.last_results: - self._update_info() + # If not initialised and not already scanned and not found. + if device not in self.last_results: + self._update_info() - if not self.last_results: - return None + if not self.last_results: + return None - return self.last_results.get(device) + return self.last_results.get(device) - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the Sky Hub is up to date. @@ -81,18 +70,17 @@ class SkyHubDeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - _LOGGER.info("Scanning") + _LOGGER.info("Scanning") - data = _get_skyhub_data(self.url) + data = _get_skyhub_data(self.url) - if not data: - _LOGGER.warning('Error scanning devices') - return False + if not data: + _LOGGER.warning('Error scanning devices') + return False - self.last_results = data + self.last_results = data - return True + return True def _get_skyhub_data(url): diff --git a/homeassistant/components/device_tracker/snmp.py b/homeassistant/components/device_tracker/snmp.py index a3be40036cb..46b1686b21d 100644 --- a/homeassistant/components/device_tracker/snmp.py +++ b/homeassistant/components/device_tracker/snmp.py @@ -6,8 +6,6 @@ https://home-assistant.io/components/device_tracker.snmp/ """ import binascii import logging -import threading -from datetime import timedelta import voluptuous as vol @@ -15,7 +13,6 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST -from homeassistant.util import Throttle _LOGGER = logging.getLogger(__name__) @@ -28,8 +25,6 @@ CONF_BASEOID = 'baseoid' DEFAULT_COMMUNITY = 'public' -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Optional(CONF_COMMUNITY, default=DEFAULT_COMMUNITY): cv.string, @@ -68,9 +63,6 @@ class SnmpScanner(DeviceScanner): privProtocol=cfg.usmAesCfb128Protocol ) self.baseoid = cmdgen.MibVariable(config[CONF_BASEOID]) - - self.lock = threading.Lock() - self.last_results = [] # Test the router is accessible @@ -90,7 +82,6 @@ class SnmpScanner(DeviceScanner): # We have no names return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the device is up to date. @@ -99,13 +90,12 @@ class SnmpScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - data = self.get_snmp_data() - if not data: - return False + data = self.get_snmp_data() + if not data: + return False - self.last_results = data - return True + self.last_results = data + return True def get_snmp_data(self): """Fetch MAC addresses from access point via SNMP.""" diff --git a/homeassistant/components/device_tracker/swisscom.py b/homeassistant/components/device_tracker/swisscom.py index d2a5a57e491..e64d30942ca 100644 --- a/homeassistant/components/device_tracker/swisscom.py +++ b/homeassistant/components/device_tracker/swisscom.py @@ -5,8 +5,6 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/device_tracker.swisscom/ """ import logging -import threading -from datetime import timedelta import requests import voluptuous as vol @@ -15,9 +13,6 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST -from homeassistant.util import Throttle - -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) _LOGGER = logging.getLogger(__name__) @@ -41,9 +36,6 @@ class SwisscomDeviceScanner(DeviceScanner): def __init__(self, config): """Initialize the scanner.""" self.host = config[CONF_HOST] - - self.lock = threading.Lock() - self.last_results = {} # Test the router is accessible. @@ -64,7 +56,6 @@ class SwisscomDeviceScanner(DeviceScanner): return client['host'] return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the Swisscom router is up to date. @@ -73,16 +64,15 @@ class SwisscomDeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - _LOGGER.info("Loading data from Swisscom Internet Box") - data = self.get_swisscom_data() - if not data: - return False + _LOGGER.info("Loading data from Swisscom Internet Box") + data = self.get_swisscom_data() + if not data: + return False - active_clients = [client for client in data.values() if - client['status']] - self.last_results = active_clients - return True + active_clients = [client for client in data.values() if + client['status']] + self.last_results = active_clients + return True def get_swisscom_data(self): """Retrieve data from Swisscom and return parsed result.""" diff --git a/homeassistant/components/device_tracker/thomson.py b/homeassistant/components/device_tracker/thomson.py index 6efe8d59beb..3fa161e467d 100644 --- a/homeassistant/components/device_tracker/thomson.py +++ b/homeassistant/components/device_tracker/thomson.py @@ -7,8 +7,6 @@ https://home-assistant.io/components/device_tracker.thomson/ import logging import re import telnetlib -import threading -from datetime import timedelta import voluptuous as vol @@ -16,9 +14,6 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle - -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10) _LOGGER = logging.getLogger(__name__) @@ -54,9 +49,6 @@ class ThomsonDeviceScanner(DeviceScanner): self.host = config[CONF_HOST] self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] - - self.lock = threading.Lock() - self.last_results = {} # Test the router is accessible. @@ -77,7 +69,6 @@ class ThomsonDeviceScanner(DeviceScanner): return client['host'] return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the THOMSON router is up to date. @@ -86,17 +77,16 @@ class ThomsonDeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - _LOGGER.info("Checking ARP") - data = self.get_thomson_data() - if not data: - return False + _LOGGER.info("Checking ARP") + data = self.get_thomson_data() + if not data: + return False - # Flag C stands for CONNECTED - active_clients = [client for client in data.values() if - client['status'].find('C') != -1] - self.last_results = active_clients - return True + # Flag C stands for CONNECTED + active_clients = [client for client in data.values() if + client['status'].find('C') != -1] + self.last_results = active_clients + return True def get_thomson_data(self): """Retrieve data from THOMSON and return parsed result.""" diff --git a/homeassistant/components/device_tracker/tomato.py b/homeassistant/components/device_tracker/tomato.py index 0b330c933d8..57e83eaeb94 100644 --- a/homeassistant/components/device_tracker/tomato.py +++ b/homeassistant/components/device_tracker/tomato.py @@ -7,8 +7,6 @@ https://home-assistant.io/components/device_tracker.tomato/ import json import logging import re -import threading -from datetime import timedelta import requests import voluptuous as vol @@ -17,9 +15,6 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle - -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) CONF_HTTP_ID = 'http_id' @@ -54,8 +49,6 @@ class TomatoDeviceScanner(DeviceScanner): self.parse_api_pattern = re.compile(r"(?P\w*) = (?P.*);") self.logger = logging.getLogger("{}.{}".format(__name__, "Tomato")) - self.lock = threading.Lock() - self.last_results = {"wldev": [], "dhcpd_lease": []} self.success_init = self._update_tomato_info() @@ -76,50 +69,48 @@ class TomatoDeviceScanner(DeviceScanner): return filter_named[0] - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_tomato_info(self): """Ensure the information from the Tomato router is up to date. Return boolean if scanning successful. """ - with self.lock: - self.logger.info("Scanning") + self.logger.info("Scanning") - try: - response = requests.Session().send(self.req, timeout=3) - # Calling and parsing the Tomato api here. We only need the - # wldev and dhcpd_lease values. - if response.status_code == 200: + try: + response = requests.Session().send(self.req, timeout=3) + # Calling and parsing the Tomato api here. We only need the + # wldev and dhcpd_lease values. + if response.status_code == 200: - for param, value in \ - self.parse_api_pattern.findall(response.text): + for param, value in \ + self.parse_api_pattern.findall(response.text): - if param == 'wldev' or param == 'dhcpd_lease': - self.last_results[param] = \ - json.loads(value.replace("'", '"')) - return True + if param == 'wldev' or param == 'dhcpd_lease': + self.last_results[param] = \ + json.loads(value.replace("'", '"')) + return True - elif response.status_code == 401: - # Authentication error - self.logger.exception(( - "Failed to authenticate, " - "please check your username and password")) - return False - - except requests.exceptions.ConnectionError: - # We get this if we could not connect to the router or - # an invalid http_id was supplied. - self.logger.exception("Failed to connect to the router or " - "invalid http_id supplied") + elif response.status_code == 401: + # Authentication error + self.logger.exception(( + "Failed to authenticate, " + "please check your username and password")) return False - except requests.exceptions.Timeout: - # We get this if we could not connect to the router or - # an invalid http_id was supplied. - self.logger.exception("Connection to the router timed out") - return False + except requests.exceptions.ConnectionError: + # We get this if we could not connect to the router or + # an invalid http_id was supplied. + self.logger.exception("Failed to connect to the router or " + "invalid http_id supplied") + return False - except ValueError: - # If JSON decoder could not parse the response. - self.logger.exception("Failed to parse response from router") - return False + except requests.exceptions.Timeout: + # We get this if we could not connect to the router or + # an invalid http_id was supplied. + self.logger.exception("Connection to the router timed out") + return False + + except ValueError: + # If JSON decoder could not parse the response. + self.logger.exception("Failed to parse response from router") + return False diff --git a/homeassistant/components/device_tracker/tplink.py b/homeassistant/components/device_tracker/tplink.py index ccf0c2d01af..a52de48d061 100755 --- a/homeassistant/components/device_tracker/tplink.py +++ b/homeassistant/components/device_tracker/tplink.py @@ -8,8 +8,7 @@ import base64 import hashlib import logging import re -import threading -from datetime import timedelta, datetime +from datetime import datetime import requests import voluptuous as vol @@ -18,9 +17,6 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle - -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) _LOGGER = logging.getLogger(__name__) @@ -59,7 +55,6 @@ class TplinkDeviceScanner(DeviceScanner): self.password = password self.last_results = {} - self.lock = threading.Lock() self.success_init = self._update_info() def scan_devices(self): @@ -72,28 +67,26 @@ class TplinkDeviceScanner(DeviceScanner): """Get firmware doesn't save the name of the wireless device.""" return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the TP-Link router is up to date. Return boolean if scanning successful. """ - with self.lock: - _LOGGER.info("Loading wireless clients...") + _LOGGER.info("Loading wireless clients...") - url = 'http://{}/userRpm/WlanStationRpm.htm'.format(self.host) - referer = 'http://{}'.format(self.host) - page = requests.get( - url, auth=(self.username, self.password), - headers={'referer': referer}, timeout=4) + url = 'http://{}/userRpm/WlanStationRpm.htm'.format(self.host) + referer = 'http://{}'.format(self.host) + page = requests.get( + url, auth=(self.username, self.password), + headers={'referer': referer}, timeout=4) - result = self.parse_macs.findall(page.text) + result = self.parse_macs.findall(page.text) - if result: - self.last_results = [mac.replace("-", ":") for mac in result] - return True + if result: + self.last_results = [mac.replace("-", ":") for mac in result] + return True - return False + return False class Tplink2DeviceScanner(TplinkDeviceScanner): @@ -109,48 +102,46 @@ class Tplink2DeviceScanner(TplinkDeviceScanner): """Get firmware doesn't save the name of the wireless device.""" return self.last_results.get(device) - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the TP-Link router is up to date. Return boolean if scanning successful. """ - with self.lock: - _LOGGER.info("Loading wireless clients...") + _LOGGER.info("Loading wireless clients...") - url = 'http://{}/data/map_access_wireless_client_grid.json' \ - .format(self.host) - referer = 'http://{}'.format(self.host) + url = 'http://{}/data/map_access_wireless_client_grid.json' \ + .format(self.host) + referer = 'http://{}'.format(self.host) - # Router uses Authorization cookie instead of header - # Let's create the cookie - username_password = '{}:{}'.format(self.username, self.password) - b64_encoded_username_password = base64.b64encode( - username_password.encode('ascii') - ).decode('ascii') - cookie = 'Authorization=Basic {}' \ - .format(b64_encoded_username_password) + # Router uses Authorization cookie instead of header + # Let's create the cookie + username_password = '{}:{}'.format(self.username, self.password) + b64_encoded_username_password = base64.b64encode( + username_password.encode('ascii') + ).decode('ascii') + cookie = 'Authorization=Basic {}' \ + .format(b64_encoded_username_password) - response = requests.post( - url, headers={'referer': referer, 'cookie': cookie}, - timeout=4) - - try: - result = response.json().get('data') - except ValueError: - _LOGGER.error("Router didn't respond with JSON. " - "Check if credentials are correct.") - return False - - if result: - self.last_results = { - device['mac_addr'].replace('-', ':'): device['name'] - for device in result - } - return True + response = requests.post( + url, headers={'referer': referer, 'cookie': cookie}, + timeout=4) + try: + result = response.json().get('data') + except ValueError: + _LOGGER.error("Router didn't respond with JSON. " + "Check if credentials are correct.") return False + if result: + self.last_results = { + device['mac_addr'].replace('-', ':'): device['name'] + for device in result + } + return True + + return False + class Tplink3DeviceScanner(TplinkDeviceScanner): """This class queries the Archer C9 router with version 150811 or high.""" @@ -202,70 +193,67 @@ class Tplink3DeviceScanner(TplinkDeviceScanner): response.text) return False - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the TP-Link router is up to date. Return boolean if scanning successful. """ - with self.lock: - if (self.stok == '') or (self.sysauth == ''): - self._get_auth_tokens() + if (self.stok == '') or (self.sysauth == ''): + self._get_auth_tokens() - _LOGGER.info("Loading wireless clients...") + _LOGGER.info("Loading wireless clients...") - url = ('http://{}/cgi-bin/luci/;stok={}/admin/wireless?' - 'form=statistics').format(self.host, self.stok) - referer = 'http://{}/webpages/index.html'.format(self.host) + url = ('http://{}/cgi-bin/luci/;stok={}/admin/wireless?' + 'form=statistics').format(self.host, self.stok) + referer = 'http://{}/webpages/index.html'.format(self.host) - response = requests.post(url, - params={'operation': 'load'}, - headers={'referer': referer}, - cookies={'sysauth': self.sysauth}, - timeout=5) + response = requests.post(url, + params={'operation': 'load'}, + headers={'referer': referer}, + cookies={'sysauth': self.sysauth}, + timeout=5) - try: - json_response = response.json() + try: + json_response = response.json() - if json_response.get('success'): - result = response.json().get('data') - else: - if json_response.get('errorcode') == 'timeout': - _LOGGER.info("Token timed out. Relogging on next scan") - self.stok = '' - self.sysauth = '' - return False - _LOGGER.error( - "An unknown error happened while fetching data") + if json_response.get('success'): + result = response.json().get('data') + else: + if json_response.get('errorcode') == 'timeout': + _LOGGER.info("Token timed out. Relogging on next scan") + self.stok = '' + self.sysauth = '' return False - except ValueError: - _LOGGER.error("Router didn't respond with JSON. " - "Check if credentials are correct") + _LOGGER.error( + "An unknown error happened while fetching data") return False - - if result: - self.last_results = { - device['mac'].replace('-', ':'): device['mac'] - for device in result - } - return True - + except ValueError: + _LOGGER.error("Router didn't respond with JSON. " + "Check if credentials are correct") return False + if result: + self.last_results = { + device['mac'].replace('-', ':'): device['mac'] + for device in result + } + return True + + return False + def _log_out(self): - with self.lock: - _LOGGER.info("Logging out of router admin interface...") + _LOGGER.info("Logging out of router admin interface...") - url = ('http://{}/cgi-bin/luci/;stok={}/admin/system?' - 'form=logout').format(self.host, self.stok) - referer = 'http://{}/webpages/index.html'.format(self.host) + url = ('http://{}/cgi-bin/luci/;stok={}/admin/system?' + 'form=logout').format(self.host, self.stok) + referer = 'http://{}/webpages/index.html'.format(self.host) - requests.post(url, - params={'operation': 'write'}, - headers={'referer': referer}, - cookies={'sysauth': self.sysauth}) - self.stok = '' - self.sysauth = '' + requests.post(url, + params={'operation': 'write'}, + headers={'referer': referer}, + cookies={'sysauth': self.sysauth}) + self.stok = '' + self.sysauth = '' class Tplink4DeviceScanner(TplinkDeviceScanner): @@ -318,38 +306,36 @@ class Tplink4DeviceScanner(TplinkDeviceScanner): _LOGGER.error("Couldn't fetch auth tokens") return False - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the TP-Link router is up to date. Return boolean if scanning successful. """ - with self.lock: - if (self.credentials == '') or (self.token == ''): - self._get_auth_tokens() + if (self.credentials == '') or (self.token == ''): + self._get_auth_tokens() - _LOGGER.info("Loading wireless clients...") + _LOGGER.info("Loading wireless clients...") - mac_results = [] + mac_results = [] - # Check both the 2.4GHz and 5GHz client list URLs - for clients_url in ('WlanStationRpm.htm', 'WlanStationRpm_5g.htm'): - url = 'http://{}/{}/userRpm/{}' \ - .format(self.host, self.token, clients_url) - referer = 'http://{}'.format(self.host) - cookie = 'Authorization=Basic {}'.format(self.credentials) + # Check both the 2.4GHz and 5GHz client list URLs + for clients_url in ('WlanStationRpm.htm', 'WlanStationRpm_5g.htm'): + url = 'http://{}/{}/userRpm/{}' \ + .format(self.host, self.token, clients_url) + referer = 'http://{}'.format(self.host) + cookie = 'Authorization=Basic {}'.format(self.credentials) - page = requests.get(url, headers={ - 'cookie': cookie, - 'referer': referer - }) - mac_results.extend(self.parse_macs.findall(page.text)) + page = requests.get(url, headers={ + 'cookie': cookie, + 'referer': referer + }) + mac_results.extend(self.parse_macs.findall(page.text)) - if not mac_results: - return False + if not mac_results: + return False - self.last_results = [mac.replace("-", ":") for mac in mac_results] - return True + self.last_results = [mac.replace("-", ":") for mac in mac_results] + return True class Tplink5DeviceScanner(TplinkDeviceScanner): @@ -365,69 +351,67 @@ class Tplink5DeviceScanner(TplinkDeviceScanner): """Get firmware doesn't save the name of the wireless device.""" return None - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the TP-Link AP is up to date. Return boolean if scanning successful. """ - with self.lock: - _LOGGER.info("Loading wireless clients...") + _LOGGER.info("Loading wireless clients...") - base_url = 'http://{}'.format(self.host) + base_url = 'http://{}'.format(self.host) - header = { - "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12;" - " rv:53.0) Gecko/20100101 Firefox/53.0", - "Accept": "application/json, text/javascript, */*; q=0.01", - "Accept-Language": "Accept-Language: en-US,en;q=0.5", - "Accept-Encoding": "gzip, deflate", - "Content-Type": "application/x-www-form-urlencoded; " - "charset=UTF-8", - "X-Requested-With": "XMLHttpRequest", - "Referer": "http://" + self.host + "/", - "Connection": "keep-alive", - "Pragma": "no-cache", - "Cache-Control": "no-cache" - } + header = { + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12;" + " rv:53.0) Gecko/20100101 Firefox/53.0", + "Accept": "application/json, text/javascript, */*; q=0.01", + "Accept-Language": "Accept-Language: en-US,en;q=0.5", + "Accept-Encoding": "gzip, deflate", + "Content-Type": "application/x-www-form-urlencoded; " + "charset=UTF-8", + "X-Requested-With": "XMLHttpRequest", + "Referer": "http://" + self.host + "/", + "Connection": "keep-alive", + "Pragma": "no-cache", + "Cache-Control": "no-cache" + } - password_md5 = hashlib.md5( - self.password.encode('utf')).hexdigest().upper() + password_md5 = hashlib.md5( + self.password.encode('utf')).hexdigest().upper() - # create a session to handle cookie easier - session = requests.session() - session.get(base_url, headers=header) + # create a session to handle cookie easier + session = requests.session() + session.get(base_url, headers=header) - login_data = {"username": self.username, "password": password_md5} - session.post(base_url, login_data, headers=header) + login_data = {"username": self.username, "password": password_md5} + session.post(base_url, login_data, headers=header) - # a timestamp is required to be sent as get parameter - timestamp = int(datetime.now().timestamp() * 1e3) + # a timestamp is required to be sent as get parameter + timestamp = int(datetime.now().timestamp() * 1e3) - client_list_url = '{}/data/monitor.client.client.json'.format( - base_url) + client_list_url = '{}/data/monitor.client.client.json'.format( + base_url) - get_params = { - 'operation': 'load', - '_': timestamp - } - - response = session.get(client_list_url, - headers=header, - params=get_params) - session.close() - try: - list_of_devices = response.json() - except ValueError: - _LOGGER.error("AP didn't respond with JSON. " - "Check if credentials are correct.") - return False - - if list_of_devices: - self.last_results = { - device['MAC'].replace('-', ':'): device['DeviceName'] - for device in list_of_devices['data'] - } - return True + get_params = { + 'operation': 'load', + '_': timestamp + } + response = session.get(client_list_url, + headers=header, + params=get_params) + session.close() + try: + list_of_devices = response.json() + except ValueError: + _LOGGER.error("AP didn't respond with JSON. " + "Check if credentials are correct.") return False + + if list_of_devices: + self.last_results = { + device['MAC'].replace('-', ':'): device['DeviceName'] + for device in list_of_devices['data'] + } + return True + + return False diff --git a/homeassistant/components/device_tracker/ubus.py b/homeassistant/components/device_tracker/ubus.py index 8d4cd1dcd73..64b9a633cbd 100644 --- a/homeassistant/components/device_tracker/ubus.py +++ b/homeassistant/components/device_tracker/ubus.py @@ -7,8 +7,6 @@ https://home-assistant.io/components/device_tracker.ubus/ import json import logging import re -import threading -from datetime import timedelta import requests import voluptuous as vol @@ -17,12 +15,8 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle from homeassistant.exceptions import HomeAssistantError -# Return cached results if last scan was less then this time ago. -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) - _LOGGER = logging.getLogger(__name__) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -70,7 +64,6 @@ class UbusDeviceScanner(DeviceScanner): self.password = config[CONF_PASSWORD] self.parse_api_pattern = re.compile(r"(?P\w*) = (?P.*);") - self.lock = threading.Lock() self.last_results = {} self.url = 'http://{}/ubus'.format(host) @@ -89,34 +82,32 @@ class UbusDeviceScanner(DeviceScanner): @_refresh_on_acccess_denied def get_device_name(self, device): """Return the name of the given device or None if we don't know.""" - with self.lock: - if self.leasefile is None: - result = _req_json_rpc( - self.url, self.session_id, 'call', 'uci', 'get', - config="dhcp", type="dnsmasq") - if result: - values = result["values"].values() - self.leasefile = next(iter(values))["leasefile"] - else: - return + if self.leasefile is None: + result = _req_json_rpc( + self.url, self.session_id, 'call', 'uci', 'get', + config="dhcp", type="dnsmasq") + if result: + values = result["values"].values() + self.leasefile = next(iter(values))["leasefile"] + else: + return - if self.mac2name is None: - result = _req_json_rpc( - self.url, self.session_id, 'call', 'file', 'read', - path=self.leasefile) - if result: - self.mac2name = dict() - for line in result["data"].splitlines(): - hosts = line.split(" ") - self.mac2name[hosts[1].upper()] = hosts[3] - else: - # Error, handled in the _req_json_rpc - return + if self.mac2name is None: + result = _req_json_rpc( + self.url, self.session_id, 'call', 'file', 'read', + path=self.leasefile) + if result: + self.mac2name = dict() + for line in result["data"].splitlines(): + hosts = line.split(" ") + self.mac2name[hosts[1].upper()] = hosts[3] + else: + # Error, handled in the _req_json_rpc + return - return self.mac2name.get(device.upper(), None) + return self.mac2name.get(device.upper(), None) @_refresh_on_acccess_denied - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the Luci router is up to date. @@ -125,25 +116,24 @@ class UbusDeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - _LOGGER.info("Checking ARP") + _LOGGER.info("Checking ARP") - if not self.hostapd: - hostapd = _req_json_rpc( - self.url, self.session_id, 'list', 'hostapd.*', '') - self.hostapd.extend(hostapd.keys()) + if not self.hostapd: + hostapd = _req_json_rpc( + self.url, self.session_id, 'list', 'hostapd.*', '') + self.hostapd.extend(hostapd.keys()) - self.last_results = [] - results = 0 - for hostapd in self.hostapd: - result = _req_json_rpc( - self.url, self.session_id, 'call', hostapd, 'get_clients') + self.last_results = [] + results = 0 + for hostapd in self.hostapd: + result = _req_json_rpc( + self.url, self.session_id, 'call', hostapd, 'get_clients') - if result: - results = results + 1 - self.last_results.extend(result['clients'].keys()) + if result: + results = results + 1 + self.last_results.extend(result['clients'].keys()) - return bool(results) + return bool(results) def _req_json_rpc(url, session_id, rpcmethod, subsystem, method, **params): diff --git a/homeassistant/components/device_tracker/volvooncall.py b/homeassistant/components/device_tracker/volvooncall.py index 9bd5727510a..4312c5dd54a 100644 --- a/homeassistant/components/device_tracker/volvooncall.py +++ b/homeassistant/components/device_tracker/volvooncall.py @@ -9,8 +9,7 @@ import logging from homeassistant.util import slugify from homeassistant.helpers.dispatcher import ( dispatcher_connect, dispatcher_send) -from homeassistant.components.volvooncall import ( - DATA_KEY, SIGNAL_VEHICLE_SEEN) +from homeassistant.components.volvooncall import DATA_KEY, SIGNAL_VEHICLE_SEEN _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/device_tracker/xiaomi.py b/homeassistant/components/device_tracker/xiaomi.py index a7b0a1ad326..8b8db3da2d8 100644 --- a/homeassistant/components/device_tracker/xiaomi.py +++ b/homeassistant/components/device_tracker/xiaomi.py @@ -5,8 +5,6 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/device_tracker.xiaomi/ """ import logging -import threading -from datetime import timedelta import requests import voluptuous as vol @@ -15,12 +13,9 @@ import homeassistant.helpers.config_validation as cv from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA, DeviceScanner) from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME -from homeassistant.util import Throttle _LOGGER = logging.getLogger(__name__) -MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5) - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_USERNAME, default='admin'): cv.string, @@ -47,8 +42,6 @@ class XiaomiDeviceScanner(DeviceScanner): self.username = config[CONF_USERNAME] self.password = config[CONF_PASSWORD] - self.lock = threading.Lock() - self.last_results = {} self.token = _get_token(self.host, self.username, self.password) @@ -62,21 +55,19 @@ class XiaomiDeviceScanner(DeviceScanner): def get_device_name(self, device): """Return the name of the given device or None if we don't know.""" - with self.lock: - if self.mac2name is None: - result = self._retrieve_list_with_retry() - if result: - hosts = [x for x in result - if 'mac' in x and 'name' in x] - mac2name_list = [ - (x['mac'].upper(), x['name']) for x in hosts] - self.mac2name = dict(mac2name_list) - else: - # Error, handled in the _retrieve_list_with_retry - return - return self.mac2name.get(device.upper(), None) + if self.mac2name is None: + result = self._retrieve_list_with_retry() + if result: + hosts = [x for x in result + if 'mac' in x and 'name' in x] + mac2name_list = [ + (x['mac'].upper(), x['name']) for x in hosts] + self.mac2name = dict(mac2name_list) + else: + # Error, handled in the _retrieve_list_with_retry + return + return self.mac2name.get(device.upper(), None) - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the informations from the router are up to date. @@ -85,12 +76,11 @@ class XiaomiDeviceScanner(DeviceScanner): if not self.success_init: return False - with self.lock: - result = self._retrieve_list_with_retry() - if result: - self._store_result(result) - return True - return False + result = self._retrieve_list_with_retry() + if result: + self._store_result(result) + return True + return False def _retrieve_list_with_retry(self): """Retrieve the device list with a retry if token is invalid. From 1d3113761698af2abd38c773ed079eccf60a9736 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 24 Jul 2017 07:47:57 -0700 Subject: [PATCH 085/118] Update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 40a393517da..62a0d0a8003 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -Home Assistant |Build Status| |Coverage Status| | Join the chat `at discord `_ | Join the dev chat `at discord `_ | +Home Assistant |Build Status| |Coverage Status| | `Join Chat `_ ============================================================================================================================================================================================== Home Assistant is a home automation platform running on Python 3. It is able to track and control all devices at home and offer a platform for automating control. From 9d9ca64f2604548b98337c39529e2c703f43c560 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 24 Jul 2017 07:53:14 -0700 Subject: [PATCH 086/118] Update README.rst --- README.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 62a0d0a8003..039e8a922af 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -Home Assistant |Build Status| |Coverage Status| | `Join Chat `_ -============================================================================================================================================================================================== +Home Assistant |Build Status| |Coverage Status| |Chat Status| +============================================================= Home Assistant is a home automation platform running on Python 3. It is able to track and control all devices at home and offer a platform for automating control. @@ -31,6 +31,8 @@ of a component, check the `Home Assistant help section Date: Tue, 25 Jul 2017 01:59:10 +1000 Subject: [PATCH 087/118] Add support for using credstash as a secret store (#8494) --- homeassistant/scripts/credstash.py | 71 ++++++++++++++++++++++++++++++ homeassistant/util/yaml.py | 14 ++++++ pylintrc | 2 + requirements_all.txt | 6 +++ tests/util/test_yaml.py | 11 +++++ 5 files changed, 104 insertions(+) create mode 100644 homeassistant/scripts/credstash.py diff --git a/homeassistant/scripts/credstash.py b/homeassistant/scripts/credstash.py new file mode 100644 index 00000000000..9ba945626e2 --- /dev/null +++ b/homeassistant/scripts/credstash.py @@ -0,0 +1,71 @@ +"""Script to get, put and delete secrets stored in credstash.""" +import argparse +import getpass + +from homeassistant.util.yaml import _SECRET_NAMESPACE + +REQUIREMENTS = ['credstash==1.13.2', 'botocore==1.4.93'] + + +def run(args): + """Handle credstash script.""" + parser = argparse.ArgumentParser( + description=("Modify Home-Assistant secrets in credstash." + "Use the secrets in configuration files with: " + "!secret ")) + parser.add_argument( + '--script', choices=['credstash']) + parser.add_argument( + 'action', choices=['get', 'put', 'del', 'list'], + help="Get, put or delete a secret, or list all available secrets") + parser.add_argument( + 'name', help="Name of the secret", nargs='?', default=None) + parser.add_argument( + 'value', help="The value to save when putting a secret", + nargs='?', default=None) + + import credstash + import botocore + + args = parser.parse_args(args) + table = _SECRET_NAMESPACE + + try: + credstash.listSecrets(table=table) + except botocore.errorfactory.ClientError: + credstash.createDdbTable(table=table) + + if args.action == 'list': + secrets = [i['name'] for i in credstash.listSecrets(table=table)] + deduped_secrets = sorted(set(secrets)) + + print('Saved secrets:') + for secret in deduped_secrets: + print(secret) + return 0 + + if args.name is None: + parser.print_help() + return 1 + + if args.action == 'put': + if args.value: + the_secret = args.value + else: + the_secret = getpass.getpass('Please enter the secret for {}: ' + .format(args.name)) + current_version = credstash.getHighestVersion(args.name, table=table) + credstash.putSecret(args.name, + the_secret, + version=int(current_version) + 1, + table=table) + print('Secret {} put successfully'.format(args.name)) + elif args.action == 'get': + the_secret = credstash.getSecret(args.name, table=table) + if the_secret is None: + print('Secret {} not found'.format(args.name)) + else: + print('Secret {}={}'.format(args.name, the_secret)) + elif args.action == 'del': + credstash.deleteSecrets(args.name, table=table) + print('Deleted secret {}'.format(args.name)) diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index 7827f484fdf..fb682ac6f19 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -12,6 +12,11 @@ try: except ImportError: keyring = None +try: + import credstash +except ImportError: + credstash = None + from homeassistant.exceptions import HomeAssistantError _LOGGER = logging.getLogger(__name__) @@ -257,6 +262,15 @@ def _secret_yaml(loader: SafeLineLoader, _LOGGER.debug("Secret %s retrieved from keyring", node.value) return pwd + if credstash: + try: + pwd = credstash.getSecret(node.value, table=_SECRET_NAMESPACE) + if pwd: + _LOGGER.debug("Secret %s retrieved from credstash", node.value) + return pwd + except credstash.ItemNotFound: + pass + _LOGGER.error("Secret %s not defined", node.value) raise HomeAssistantError(node.value) diff --git a/pylintrc b/pylintrc index e94cbffe9f9..1ed8d2af336 100644 --- a/pylintrc +++ b/pylintrc @@ -14,6 +14,8 @@ reports=no # too-few-* - same as too-many-* # abstract-method - with intro of async there are always methods missing +generated-members=botocore.errorfactory + disable= abstract-class-little-used, abstract-class-not-used, diff --git a/requirements_all.txt b/requirements_all.txt index 10036a03615..aa99cd03701 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -115,6 +115,9 @@ blockchain==1.3.3 # homeassistant.components.tts.amazon_polly boto3==1.4.3 +# homeassistant.scripts.credstash +botocore==1.4.93 + # homeassistant.components.sensor.broadlink # homeassistant.components.switch.broadlink broadlink==0.5 @@ -136,6 +139,9 @@ colorlog>2.1,<3 # homeassistant.components.binary_sensor.concord232 concord232==0.14 +# homeassistant.scripts.credstash +credstash==1.13.2 + # homeassistant.components.sensor.crimereports crimereports==1.0.0 diff --git a/tests/util/test_yaml.py b/tests/util/test_yaml.py index 0ccb6f5d6d0..c2eda2401f5 100644 --- a/tests/util/test_yaml.py +++ b/tests/util/test_yaml.py @@ -2,6 +2,7 @@ import io import os import unittest +import logging from unittest.mock import patch from homeassistant.exceptions import HomeAssistantError @@ -372,6 +373,16 @@ class TestSecrets(unittest.TestCase): _yaml = load_yaml(self._yaml_path, yaml_str) self.assertEqual({'http': {'api_password': 'yeah'}}, _yaml) + @patch.object(yaml, 'credstash') + def test_secrets_credstash(self, mock_credstash): + """Test credstash fallback & get_password.""" + mock_credstash.getSecret.return_value = 'yeah' + yaml_str = 'http:\n api_password: !secret http_pw_credstash' + _yaml = load_yaml(self._yaml_path, yaml_str) + log = logging.getLogger() + log.error(_yaml['http']) + self.assertEqual({'api_password': 'yeah'}, _yaml['http']) + def test_secrets_logger_removed(self): """Ensure logger: debug was removed.""" with self.assertRaises(yaml.HomeAssistantError): From ecc1429453fa7727e749ecceee069253f154aea6 Mon Sep 17 00:00:00 2001 From: Corey Pauley Date: Mon, 24 Jul 2017 11:00:01 -0500 Subject: [PATCH 088/118] Added support for default value when environment variable is missing (#8484) * Added support for a default value when an environment variable is missing * Shouldn't have used docstring --- homeassistant/util/yaml.py | 9 +++++++-- tests/util/test_yaml.py | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index fb682ac6f19..4129a67bf57 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -205,8 +205,13 @@ def _construct_seq(loader: SafeLineLoader, node: yaml.nodes.Node): def _env_var_yaml(loader: SafeLineLoader, node: yaml.nodes.Node): """Load environment variables and embed it into the configuration YAML.""" - if node.value in os.environ: - return os.environ[node.value] + args = node.value.split() + + # Check for a default value + if len(args) > 1: + return os.getenv(args[0], ' '.join(args[1:])) + elif args[0] in os.environ: + return os.environ[args[0]] else: _LOGGER.error("Environment variable %s not defined.", node.value) raise HomeAssistantError(node.value) diff --git a/tests/util/test_yaml.py b/tests/util/test_yaml.py index c2eda2401f5..a15efb7a77e 100644 --- a/tests/util/test_yaml.py +++ b/tests/util/test_yaml.py @@ -60,6 +60,13 @@ class TestYaml(unittest.TestCase): assert doc['password'] == "secret_password" del os.environ["PASSWORD"] + def test_environment_variable_default(self): + """Test config file with default value for environment variable.""" + conf = "password: !env_var PASSWORD secret_password" + with io.StringIO(conf) as file: + doc = yaml.yaml.safe_load(file) + assert doc['password'] == "secret_password" + def test_invalid_enviroment_variable(self): """Test config file with no enviroment variable sat.""" conf = "password: !env_var PASSWORD" From cc03f7ee6a566e72972c823c86f6318179dcfbb1 Mon Sep 17 00:00:00 2001 From: Colin O'Dell Date: Mon, 24 Jul 2017 12:06:38 -0400 Subject: [PATCH 089/118] Manual alarm with MQTT control (#8257) * Manual alarm with MQTT control * Duplicate manual control panel code instead of extending it * Duplicate manual alarm test as well; modify for manual_mqtt * Add MQTT-specific tests for manual_mqtt alarm --- .coveragerc | 1 + .../alarm_control_panel/manual_mqtt.py | 235 ++++++++ .../alarm_control_panel/test_manual_mqtt.py | 559 ++++++++++++++++++ 3 files changed, 795 insertions(+) create mode 100644 homeassistant/components/alarm_control_panel/manual_mqtt.py create mode 100644 tests/components/alarm_control_panel/test_manual_mqtt.py diff --git a/.coveragerc b/.coveragerc index 3ec0b119cb8..dc2f39b9977 100644 --- a/.coveragerc +++ b/.coveragerc @@ -211,6 +211,7 @@ omit = homeassistant/components/alarm_control_panel/alarmdotcom.py homeassistant/components/alarm_control_panel/concord232.py + homeassistant/components/alarm_control_panel/manual_mqtt.py homeassistant/components/alarm_control_panel/nx584.py homeassistant/components/alarm_control_panel/simplisafe.py homeassistant/components/alarm_control_panel/totalconnect.py diff --git a/homeassistant/components/alarm_control_panel/manual_mqtt.py b/homeassistant/components/alarm_control_panel/manual_mqtt.py new file mode 100644 index 00000000000..b554a667b2a --- /dev/null +++ b/homeassistant/components/alarm_control_panel/manual_mqtt.py @@ -0,0 +1,235 @@ +""" +Support for manual alarms controllable via MQTT. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/alarm_control_panel.manual_mqtt/ +""" +import asyncio +import datetime +import logging + +import voluptuous as vol + +import homeassistant.components.alarm_control_panel as alarm +import homeassistant.util.dt as dt_util +from homeassistant.const import ( + STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, + STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, CONF_PLATFORM, + CONF_NAME, CONF_CODE, CONF_PENDING_TIME, CONF_TRIGGER_TIME, + CONF_DISARM_AFTER_TRIGGER) +import homeassistant.components.mqtt as mqtt + +from homeassistant.helpers.event import async_track_state_change +from homeassistant.core import callback + +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.event import track_point_in_time + +CONF_PAYLOAD_DISARM = 'payload_disarm' +CONF_PAYLOAD_ARM_HOME = 'payload_arm_home' +CONF_PAYLOAD_ARM_AWAY = 'payload_arm_away' + +DEFAULT_ALARM_NAME = 'HA Alarm' +DEFAULT_PENDING_TIME = 60 +DEFAULT_TRIGGER_TIME = 120 +DEFAULT_DISARM_AFTER_TRIGGER = False +DEFAULT_ARM_AWAY = 'ARM_AWAY' +DEFAULT_ARM_HOME = 'ARM_HOME' +DEFAULT_DISARM = 'DISARM' + +DEPENDENCIES = ['mqtt'] + +PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({ + vol.Required(CONF_PLATFORM): 'manual_mqtt', + vol.Optional(CONF_NAME, default=DEFAULT_ALARM_NAME): cv.string, + vol.Optional(CONF_CODE): cv.string, + vol.Optional(CONF_PENDING_TIME, default=DEFAULT_PENDING_TIME): + vol.All(vol.Coerce(int), vol.Range(min=0)), + vol.Optional(CONF_TRIGGER_TIME, default=DEFAULT_TRIGGER_TIME): + vol.All(vol.Coerce(int), vol.Range(min=1)), + vol.Optional(CONF_DISARM_AFTER_TRIGGER, + default=DEFAULT_DISARM_AFTER_TRIGGER): cv.boolean, + vol.Required(mqtt.CONF_COMMAND_TOPIC): mqtt.valid_publish_topic, + vol.Required(mqtt.CONF_STATE_TOPIC): mqtt.valid_subscribe_topic, + vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string, + vol.Optional(CONF_PAYLOAD_ARM_HOME, default=DEFAULT_ARM_HOME): cv.string, + vol.Optional(CONF_PAYLOAD_DISARM, default=DEFAULT_DISARM): cv.string, +}) + +_LOGGER = logging.getLogger(__name__) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the manual MQTT alarm platform.""" + add_devices([ManualMQTTAlarm( + hass, + config[CONF_NAME], + config.get(CONF_CODE), + config.get(CONF_PENDING_TIME, DEFAULT_PENDING_TIME), + config.get(CONF_TRIGGER_TIME, DEFAULT_TRIGGER_TIME), + config.get(CONF_DISARM_AFTER_TRIGGER, DEFAULT_DISARM_AFTER_TRIGGER), + config.get(mqtt.CONF_STATE_TOPIC), + config.get(mqtt.CONF_COMMAND_TOPIC), + config.get(mqtt.CONF_QOS), + config.get(CONF_PAYLOAD_DISARM), + config.get(CONF_PAYLOAD_ARM_HOME), + config.get(CONF_PAYLOAD_ARM_AWAY))]) + + +class ManualMQTTAlarm(alarm.AlarmControlPanel): + """ + Representation of an alarm status. + + When armed, will be pending for 'pending_time', after that armed. + When triggered, will be pending for 'trigger_time'. After that will be + triggered for 'trigger_time', after that we return to the previous state + or disarm if `disarm_after_trigger` is true. + """ + + def __init__(self, hass, name, code, pending_time, + trigger_time, disarm_after_trigger, + state_topic, command_topic, qos, + payload_disarm, payload_arm_home, payload_arm_away): + """Init the manual MQTT alarm panel.""" + self._state = STATE_ALARM_DISARMED + self._hass = hass + self._name = name + self._code = str(code) if code else None + self._pending_time = datetime.timedelta(seconds=pending_time) + self._trigger_time = datetime.timedelta(seconds=trigger_time) + self._disarm_after_trigger = disarm_after_trigger + self._pre_trigger_state = self._state + self._state_ts = None + + self._state_topic = state_topic + self._command_topic = command_topic + self._qos = qos + self._payload_disarm = payload_disarm + self._payload_arm_home = payload_arm_home + self._payload_arm_away = payload_arm_away + + @property + def should_poll(self): + """Return the polling state.""" + return False + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def state(self): + """Return the state of the device.""" + if self._state in (STATE_ALARM_ARMED_HOME, + STATE_ALARM_ARMED_AWAY) and \ + self._pending_time and self._state_ts + self._pending_time > \ + dt_util.utcnow(): + return STATE_ALARM_PENDING + + if self._state == STATE_ALARM_TRIGGERED and self._trigger_time: + if self._state_ts + self._pending_time > dt_util.utcnow(): + return STATE_ALARM_PENDING + elif (self._state_ts + self._pending_time + + self._trigger_time) < dt_util.utcnow(): + if self._disarm_after_trigger: + return STATE_ALARM_DISARMED + return self._pre_trigger_state + + return self._state + + @property + def code_format(self): + """One or more characters.""" + return None if self._code is None else '.+' + + def alarm_disarm(self, code=None): + """Send disarm command.""" + if not self._validate_code(code, STATE_ALARM_DISARMED): + return + + self._state = STATE_ALARM_DISARMED + self._state_ts = dt_util.utcnow() + self.schedule_update_ha_state() + + def alarm_arm_home(self, code=None): + """Send arm home command.""" + if not self._validate_code(code, STATE_ALARM_ARMED_HOME): + return + + self._state = STATE_ALARM_ARMED_HOME + self._state_ts = dt_util.utcnow() + self.schedule_update_ha_state() + + if self._pending_time: + track_point_in_time( + self._hass, self.async_update_ha_state, + self._state_ts + self._pending_time) + + def alarm_arm_away(self, code=None): + """Send arm away command.""" + if not self._validate_code(code, STATE_ALARM_ARMED_AWAY): + return + + self._state = STATE_ALARM_ARMED_AWAY + self._state_ts = dt_util.utcnow() + self.schedule_update_ha_state() + + if self._pending_time: + track_point_in_time( + self._hass, self.async_update_ha_state, + self._state_ts + self._pending_time) + + def alarm_trigger(self, code=None): + """Send alarm trigger command. No code needed.""" + self._pre_trigger_state = self._state + self._state = STATE_ALARM_TRIGGERED + self._state_ts = dt_util.utcnow() + self.schedule_update_ha_state() + + if self._trigger_time: + track_point_in_time( + self._hass, self.async_update_ha_state, + self._state_ts + self._pending_time) + + track_point_in_time( + self._hass, self.async_update_ha_state, + self._state_ts + self._pending_time + self._trigger_time) + + def _validate_code(self, code, state): + """Validate given code.""" + check = self._code is None or code == self._code + if not check: + _LOGGER.warning("Invalid code given for %s", state) + return check + + def async_added_to_hass(self): + """Subscribe mqtt events. + + This method must be run in the event loop and returns a coroutine. + """ + async_track_state_change( + self.hass, self.entity_id, self._async_state_changed_listener + ) + + @callback + def message_received(topic, payload, qos): + """Run when new MQTT message has been received.""" + if payload == self._payload_disarm: + self.async_alarm_disarm(self._code) + elif payload == self._payload_arm_home: + self.async_alarm_arm_home(self._code) + elif payload == self._payload_arm_away: + self.async_alarm_arm_away(self._code) + else: + _LOGGER.warning("Received unexpected payload: %s", payload) + return + + return mqtt.async_subscribe( + self.hass, self._command_topic, message_received, self._qos) + + @asyncio.coroutine + def _async_state_changed_listener(self, entity_id, old_state, new_state): + """Publish state change to MQTT.""" + mqtt.async_publish(self.hass, self._state_topic, new_state.state, + self._qos, True) diff --git a/tests/components/alarm_control_panel/test_manual_mqtt.py b/tests/components/alarm_control_panel/test_manual_mqtt.py new file mode 100644 index 00000000000..c4dcd57ca39 --- /dev/null +++ b/tests/components/alarm_control_panel/test_manual_mqtt.py @@ -0,0 +1,559 @@ +"""The tests for the manual_mqtt Alarm Control Panel component.""" +from datetime import timedelta +import unittest +from unittest.mock import patch + +from homeassistant.setup import setup_component +from homeassistant.const import ( + STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_AWAY, + STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED) +from homeassistant.components import alarm_control_panel +import homeassistant.util.dt as dt_util + +from tests.common import ( + fire_time_changed, get_test_home_assistant, + mock_mqtt_component, fire_mqtt_message, assert_setup_component) + +CODE = 'HELLO_CODE' + + +class TestAlarmControlPanelManualMqtt(unittest.TestCase): + """Test the manual_mqtt alarm module.""" + + def setUp(self): # pylint: disable=invalid-name + """Setup things to be run when tests are started.""" + self.hass = get_test_home_assistant() + self.mock_publish = mock_mqtt_component(self.hass) + + def tearDown(self): # pylint: disable=invalid-name + """Stop down everything that was started.""" + self.hass.stop() + + def test_fail_setup_without_state_topic(self): + """Test for failing with no state topic.""" + with assert_setup_component(0) as config: + assert setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { + 'platform': 'mqtt_alarm', + 'command_topic': 'alarm/command' + } + }) + assert not config[alarm_control_panel.DOMAIN] + + def test_fail_setup_without_command_topic(self): + """Test failing with no command topic.""" + with assert_setup_component(0): + assert setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { + 'platform': 'mqtt_alarm', + 'state_topic': 'alarm/state' + } + }) + + def test_arm_home_no_pending(self): + """Test arm home method.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'code': CODE, + 'pending_time': 0, + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_arm_home(self.hass, CODE) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_ARMED_HOME, + self.hass.states.get(entity_id).state) + + def test_arm_home_with_pending(self): + """Test arm home method.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'code': CODE, + 'pending_time': 1, + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_arm_home(self.hass, CODE, entity_id) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + future = dt_util.utcnow() + timedelta(seconds=1) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_ARMED_HOME, + self.hass.states.get(entity_id).state) + + def test_arm_home_with_invalid_code(self): + """Attempt to arm home without a valid code.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'code': CODE, + 'pending_time': 1, + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_arm_home(self.hass, CODE + '2') + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + def test_arm_away_no_pending(self): + """Test arm home method.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'code': CODE, + 'pending_time': 0, + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_arm_away(self.hass, CODE, entity_id) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_ARMED_AWAY, + self.hass.states.get(entity_id).state) + + def test_arm_away_with_pending(self): + """Test arm home method.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'code': CODE, + 'pending_time': 1, + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_arm_away(self.hass, CODE) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + future = dt_util.utcnow() + timedelta(seconds=1) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_ARMED_AWAY, + self.hass.states.get(entity_id).state) + + def test_arm_away_with_invalid_code(self): + """Attempt to arm away without a valid code.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'code': CODE, + 'pending_time': 1, + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_arm_away(self.hass, CODE + '2') + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + def test_trigger_no_pending(self): + """Test triggering when no pending submitted method.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'trigger_time': 1, + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_trigger(self.hass, entity_id=entity_id) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + future = dt_util.utcnow() + timedelta(seconds=60) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_TRIGGERED, + self.hass.states.get(entity_id).state) + + def test_trigger_with_pending(self): + """Test arm home method.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'pending_time': 2, + 'trigger_time': 3, + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_trigger(self.hass) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + future = dt_util.utcnow() + timedelta(seconds=2) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_TRIGGERED, + self.hass.states.get(entity_id).state) + + future = dt_util.utcnow() + timedelta(seconds=5) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + def test_trigger_with_disarm_after_trigger(self): + """Test disarm after trigger.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'trigger_time': 5, + 'pending_time': 0, + 'disarm_after_trigger': True, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_trigger(self.hass, entity_id=entity_id) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_TRIGGERED, + self.hass.states.get(entity_id).state) + + future = dt_util.utcnow() + timedelta(seconds=5) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + def test_disarm_while_pending_trigger(self): + """Test disarming while pending state.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'trigger_time': 5, + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_trigger(self.hass) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_disarm(self.hass, entity_id=entity_id) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + future = dt_util.utcnow() + timedelta(seconds=5) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + def test_disarm_during_trigger_with_invalid_code(self): + """Test disarming while code is invalid.""" + self.assertTrue(setup_component( + self.hass, alarm_control_panel.DOMAIN, + {'alarm_control_panel': { + 'platform': 'manual_mqtt', + 'name': 'test', + 'pending_time': 5, + 'code': CODE + '2', + 'disarm_after_trigger': False, + 'command_topic': 'alarm/command', + 'state_topic': 'alarm/state', + }})) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_trigger(self.hass) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_disarm(self.hass, entity_id=entity_id) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + future = dt_util.utcnow() + timedelta(seconds=5) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_TRIGGERED, + self.hass.states.get(entity_id).state) + + def test_arm_home_via_command_topic(self): + """Test arming home via command topic.""" + assert setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { + 'platform': 'manual_mqtt', + 'name': 'test', + 'pending_time': 1, + 'state_topic': 'alarm/state', + 'command_topic': 'alarm/command', + 'payload_arm_home': 'ARM_HOME', + } + }) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + # Fire the arm command via MQTT; ensure state changes to pending + fire_mqtt_message(self.hass, 'alarm/command', 'ARM_HOME') + self.hass.block_till_done() + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + # Fast-forward a little bit + future = dt_util.utcnow() + timedelta(seconds=1) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_ARMED_HOME, + self.hass.states.get(entity_id).state) + + def test_arm_away_via_command_topic(self): + """Test arming away via command topic.""" + assert setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { + 'platform': 'manual_mqtt', + 'name': 'test', + 'pending_time': 1, + 'state_topic': 'alarm/state', + 'command_topic': 'alarm/command', + 'payload_arm_away': 'ARM_AWAY', + } + }) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + # Fire the arm command via MQTT; ensure state changes to pending + fire_mqtt_message(self.hass, 'alarm/command', 'ARM_AWAY') + self.hass.block_till_done() + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + # Fast-forward a little bit + future = dt_util.utcnow() + timedelta(seconds=1) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_ARMED_AWAY, + self.hass.states.get(entity_id).state) + + def test_disarm_pending_via_command_topic(self): + """Test disarming pending alarm via command topic.""" + assert setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { + 'platform': 'manual_mqtt', + 'name': 'test', + 'pending_time': 1, + 'state_topic': 'alarm/state', + 'command_topic': 'alarm/command', + 'payload_disarm': 'DISARM', + } + }) + + entity_id = 'alarm_control_panel.test' + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + alarm_control_panel.alarm_trigger(self.hass) + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_PENDING, + self.hass.states.get(entity_id).state) + + # Now that we're pending, receive a command to disarm + fire_mqtt_message(self.hass, 'alarm/command', 'DISARM') + self.hass.block_till_done() + + self.assertEqual(STATE_ALARM_DISARMED, + self.hass.states.get(entity_id).state) + + def test_state_changes_are_published_to_mqtt(self): + """Test publishing of MQTT messages when state changes.""" + assert setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { + 'platform': 'manual_mqtt', + 'name': 'test', + 'pending_time': 1, + 'trigger_time': 1, + 'state_topic': 'alarm/state', + 'command_topic': 'alarm/command', + } + }) + + # Component should send disarmed alarm state on startup + self.hass.block_till_done() + self.assertEqual(('alarm/state', STATE_ALARM_DISARMED, 0, True), + self.mock_publish.mock_calls[-2][1]) + + # Arm in home mode + alarm_control_panel.alarm_arm_home(self.hass) + self.hass.block_till_done() + self.assertEqual(('alarm/state', STATE_ALARM_PENDING, 0, True), + self.mock_publish.mock_calls[-2][1]) + # Fast-forward a little bit + future = dt_util.utcnow() + timedelta(seconds=1) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + self.assertEqual(('alarm/state', STATE_ALARM_ARMED_HOME, 0, True), + self.mock_publish.mock_calls[-2][1]) + + # Arm in away mode + alarm_control_panel.alarm_arm_away(self.hass) + self.hass.block_till_done() + self.assertEqual(('alarm/state', STATE_ALARM_PENDING, 0, True), + self.mock_publish.mock_calls[-2][1]) + # Fast-forward a little bit + future = dt_util.utcnow() + timedelta(seconds=1) + with patch(('homeassistant.components.alarm_control_panel.manual_mqtt.' + 'dt_util.utcnow'), return_value=future): + fire_time_changed(self.hass, future) + self.hass.block_till_done() + self.assertEqual(('alarm/state', STATE_ALARM_ARMED_AWAY, 0, True), + self.mock_publish.mock_calls[-2][1]) + + # Disarm + alarm_control_panel.alarm_disarm(self.hass) + self.hass.block_till_done() + self.assertEqual(('alarm/state', STATE_ALARM_DISARMED, 0, True), + self.mock_publish.mock_calls[-2][1]) From 3b7f16f189e632b574f91c41f81543941119c992 Mon Sep 17 00:00:00 2001 From: Adam Mills Date: Tue, 25 Jul 2017 00:05:47 -0400 Subject: [PATCH 090/118] Catch and log Lyft API errors (#8635) --- homeassistant/components/sensor/lyft.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/sensor/lyft.py b/homeassistant/components/sensor/lyft.py index c16fae9f5d5..11ca07f7fb8 100644 --- a/homeassistant/components/sensor/lyft.py +++ b/homeassistant/components/sensor/lyft.py @@ -45,20 +45,27 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Lyft sensor.""" from lyft_rides.auth import ClientCredentialGrant + from lyft_rides.errors import APIError auth_flow = ClientCredentialGrant(client_id=config.get(CONF_CLIENT_ID), client_secret=config.get( CONF_CLIENT_SECRET), scopes="public", is_sandbox_mode=False) - session = auth_flow.get_session() + try: + session = auth_flow.get_session() + + timeandpriceest = LyftEstimate( + session, config[CONF_START_LATITUDE], config[CONF_START_LONGITUDE], + config.get(CONF_END_LATITUDE), config.get(CONF_END_LONGITUDE)) + timeandpriceest.fetch_data() + except APIError as exc: + _LOGGER.error("Error setting up Lyft platform: %s", exc) + return False wanted_product_ids = config.get(CONF_PRODUCT_IDS) dev = [] - timeandpriceest = LyftEstimate( - session, config[CONF_START_LATITUDE], config[CONF_START_LONGITUDE], - config.get(CONF_END_LATITUDE), config.get(CONF_END_LONGITUDE)) for product_id, product in timeandpriceest.products.items(): if (wanted_product_ids is not None) and \ (product_id not in wanted_product_ids): @@ -188,14 +195,18 @@ class LyftEstimate(object): self.end_latitude = end_latitude self.end_longitude = end_longitude self.products = None - self.__real_update() @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Get the latest product info and estimates from the Lyft API.""" - self.__real_update() + from lyft_rides.errors import APIError + try: + self.fetch_data() + except APIError as exc: + _LOGGER.error("Error fetching Lyft data: %s", exc) - def __real_update(self): + def fetch_data(self): + """Get the latest product info and estimates from the Lyft API.""" from lyft_rides.client import LyftRidesClient client = LyftRidesClient(self._session) From ad7370e1c25ed4aa9e69ea1a425731c16d9504af Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 25 Jul 2017 00:29:05 -0700 Subject: [PATCH 091/118] Update frontend --- homeassistant/components/frontend/version.py | 20 +++++++++--------- .../frontend/www_static/frontend.html | 8 +++---- .../frontend/www_static/frontend.html.gz | Bin 138831 -> 139371 bytes .../www_static/home-assistant-polymer | 2 +- .../panels/ha-panel-automation.html | 2 +- .../panels/ha-panel-automation.html.gz | Bin 28564 -> 28583 bytes .../www_static/panels/ha-panel-config.html | 2 +- .../www_static/panels/ha-panel-config.html.gz | Bin 15057 -> 15061 bytes .../www_static/panels/ha-panel-dev-event.html | 2 +- .../panels/ha-panel-dev-event.html.gz | Bin 2743 -> 2730 bytes .../panels/ha-panel-dev-service.html | 2 +- .../panels/ha-panel-dev-service.html.gz | Bin 23776 -> 23797 bytes .../www_static/panels/ha-panel-dev-state.html | 2 +- .../panels/ha-panel-dev-state.html.gz | Bin 2956 -> 2943 bytes .../panels/ha-panel-dev-template.html | 2 +- .../panels/ha-panel-dev-template.html.gz | Bin 11433 -> 11445 bytes .../www_static/panels/ha-panel-map.html | 2 +- .../www_static/panels/ha-panel-map.html.gz | Bin 44197 -> 44202 bytes .../panels/ha-panel-shopping-list.html | 2 +- .../panels/ha-panel-shopping-list.html.gz | Bin 5303 -> 5308 bytes .../www_static/panels/ha-panel-zwave.html | 2 +- .../www_static/panels/ha-panel-zwave.html.gz | Bin 10543 -> 10548 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2487 -> 2490 bytes .../www_static/webcomponents-lite.min.js.gz | Bin 12360 -> 12334 bytes 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index ddfd8a33051..a0958f65d95 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -3,22 +3,22 @@ FINGERPRINTS = { "compatibility.js": "8e4c44b5f4288cc48ec1ba94a9bec812", "core.js": "d4a7cb8c80c62b536764e0e81385f6aa", - "frontend.html": "d0142106cf282596062e5b2060128f81", + "frontend.html": "c44e49b9a0d9b9e4a626b7af34ca97d0", "mdi.html": "e91f61a039ed0a9936e7ee5360da3870", "micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a", - "panels/ha-panel-automation.html": "72a5c1856cece8d9246328e84185ab0b", - "panels/ha-panel-config.html": "5e2df66aa534c4dadd08c60c361f5d45", - "panels/ha-panel-dev-event.html": "4886c821235492b1b92739b580d21c61", + "panels/ha-panel-automation.html": "1982116c49ad26ee8d89295edc797084", + "panels/ha-panel-config.html": "fafeac72f83dd6cc42218f8978f6a7af", + "panels/ha-panel-dev-event.html": "77784d5f0c73fcc3b29b6cc050bdf324", "panels/ha-panel-dev-info.html": "24e888ec7a8acd0c395b34396e9001bc", - "panels/ha-panel-dev-service.html": "ac2c50e486927dc4443e93d79f08c06e", - "panels/ha-panel-dev-state.html": "8f1a27c04db6329d31cfcc7d0d6a0869", - "panels/ha-panel-dev-template.html": "82cd543177c417e5c6612e07df851e6b", + "panels/ha-panel-dev-service.html": "86a42a17f4894478b6b77bc636beafd0", + "panels/ha-panel-dev-state.html": "31ef6ffe3347cdda5bb0cbbc54b62cde", + "panels/ha-panel-dev-template.html": "d1d76e20fe9622cddee33e67318abde8", "panels/ha-panel-hassio.html": "262d31efd9add719e0325da5cf79a096", "panels/ha-panel-history.html": "35177e2046c9a4191c8f51f8160255ce", "panels/ha-panel-iframe.html": "238189f21e670b6dcfac937e5ebd7d3b", "panels/ha-panel-kiosk.html": "2ac2df41bd447600692a0054892fc094", "panels/ha-panel-logbook.html": "7c45bd41c146ec38b9938b8a5188bb0d", - "panels/ha-panel-map.html": "b4923812c695dd8a69ad3da380ffe7b4", - "panels/ha-panel-shopping-list.html": "75602d06b41702c8093bd91c10374101", - "panels/ha-panel-zwave.html": "8c8e7844d33163f560e1f691550a8369" + "panels/ha-panel-map.html": "50501cd53eb4304e9e46eb719aa894b7", + "panels/ha-panel-shopping-list.html": "c04af28c6475b90cbf2cf63ba1b841d0", + "panels/ha-panel-zwave.html": "422f95f820f8b6b231265351ffcf4dd1" } diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index ad1e407587e..ca86fd55d22 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 +;if(t)for(var n in e){var r=t[n];if(r)for(var s,i=0,o=r.length;i1){for(var a=0;a+~])"},resolveCss:Polymer.ResolveUrl.resolveCss,parser:Polymer.CssParse,ruleTypes:Polymer.CssParse.types}}(),Polymer.StyleTransformer=function(){var e=Polymer.StyleUtil,t=Polymer.Settings,n={dom:function(e,t,n,r){this._transformDom(e,t||"",n,r)},_transformDom:function(e,t,n,r){e.setAttribute&&this.element(e,t,n,r);for(var s=Polymer.dom(e).childNodes,i=0;i *"),r&&r(e)}}for(var u,f=0,p=i.length;f *"),e=e.replace(P,l+" $1"),e=e.replace(o,function(e,i,o){if(r)o=o.replace(_," ");else{var l=a._transformCompoundSelector(o,i,t,n);r=r||l.stop,s=s||l.hostContext,i=l.combinator,o=l.value}return i+o}),s&&(e=e.replace(f,function(e,t,r,s){return t+r+" "+n+s+i+" "+t+n+r+s})),e},_transformCompoundSelector:function(e,t,n,r){var s=e.search(_),i=!1;e.indexOf(u)>=0?i=!0:e.indexOf(l)>=0?e=this._transformHostSelector(e,r):0!==s&&(e=n?this._transformSimpleSelector(e,n):e),e.indexOf(p)>=0&&(t="");var o;return s>=0&&(e=e.replace(_," "),o=!0),{value:e,combinator:t,stop:o,hostContext:i}},_transformSimpleSelector:function(e,t){var n=e.split(v);return n[0]+=t,n.join(v)},_transformHostSelector:function(e,t){var n=e.match(h),r=n&&n[2].trim()||"";if(r){if(r[0].match(a))return e.replace(h,function(e,n,r){return t+r});return r.split(a)[0]===t?r:S}return e.replace(l,t)},documentRule:function(e){e.selector=e.parsedSelector,this.normalizeRootSelector(e),t.useNativeShadow||this._transformRule(e,this._transformDocumentSelector)},normalizeRootSelector:function(e){e.selector=e.selector.replace(c,"html");var t=e.selector.split(i);t=t.filter(function(e){return!e.match(C)}),e.selector=t.join(i)},_transformDocumentSelector:function(e){return e.match(_)?this._transformComplexSelector(e,s):this._transformSimpleSelector(e.trim(),s)},_slottedToContent:function(e){return e.replace(E,p+"> $1")},SCOPE_NAME:"style-scope"},r=n.SCOPE_NAME,s=":not(["+r+"]):not(."+r+")",i=",",o=/(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=\[])+)/g,a=/[[.:#*]/,l=":host",c=":root",h=/(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/,u=":host-context",f=/(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/,p="::content",_=/::content|::shadow|\/deep\//,d=".",m="["+r+"~=",y="]",v=":",g="class",P=new RegExp("^("+p+")"),S="should_not_match",E=/(?:::slotted)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g,C=/:host(?:\s*>\s*\*)?/;return n}(),Polymer.StyleExtends=function(){var e=Polymer.StyleUtil;return{hasExtends:function(e){return Boolean(e.match(this.rx.EXTEND))},transform:function(t){var n=e.rulesForStyle(t),r=this;return e.forEachRule(n,function(e){if(r._mapRuleOntoParent(e),e.parent)for(var t;t=r.rx.EXTEND.exec(e.cssText);){var n=t[1],s=r._findExtendor(n,e);s&&r._extendRule(e,s)}e.cssText=e.cssText.replace(r.rx.EXTEND,"")}),e.toCssText(n,function(e){e.selector.match(r.rx.STRIP)&&(e.cssText="")},!0)},_mapRuleOntoParent:function(e){if(e.parent){for(var t,n=e.parent.map||(e.parent.map={}),r=e.selector.split(","),s=0;s1&&(t=i[0].trim(),r=n(t,i.slice(1).join(":")),a[t]=r));return a}function s(e){var t=m.__currentElementProto,n=t&&t.is;for(var r in e.dependants)r!==n&&(e.dependants[r].__applyShimInvalid=!0)}function i(n,i,o,a){if(o&&c.processVariableAndFallback(o,function(e,n){n&&t(n)&&(a="@apply "+n+";")}),!a)return n;var h=l(a),u=n.slice(0,n.indexOf("--")),f=r(h),p=f,d=t(i),m=d&&d.properties;m?(p=Object.create(m),p=Polymer.Base.mixin(p,f)):e(i,p);var y,v,g=[],P=!1;for(y in p)v=f[y],void 0===v&&(v="initial"),!m||y in m||(P=!0),g.push(i+_+y+": "+v);return P&&s(d),d&&(d.properties=p),o&&(u=n+";"+u),u+g.join("; ")+";"}function o(e,t,n){return"var("+t+",var("+n+"))"}function a(n,r){n=n.replace(f,"");var s=[],i=t(n);if(i||(e(n,{}),i=t(n)),i){var o=m.__currentElementProto;o&&(i.dependants[o.is]=o);var a,l,c;for(a in i.properties)c=r&&r[a],l=[a,": var(",n,_,a],c&&l.push(",",c),l.push(")"),s.push(l.join(""))}return s.join("; ")}function l(e){for(var t;t=h.exec(e);){var n=t[0],s=t[1],i=t.index,o=i+n.indexOf("@apply"),l=i+n.length,c=e.slice(0,o),u=e.slice(l),f=r(c),p=a(s,f);e=[c,p,u].join(""),h.lastIndex=i+p.length}return e}var c=Polymer.StyleUtil,h=c.rx.MIXIN_MATCH,u=c.rx.VAR_ASSIGN,f=/;\s*/m,p=/^\s*(initial)|(inherit)\s*$/,_="_-_",d={},m={_measureElement:null,_map:d,_separator:_,transform:function(e,t){this.__currentElementProto=t,c.forRulesInStyles(e,this._boundFindDefinitions),c.forRulesInStyles(e,this._boundFindApplications),t&&(t.__applyShimInvalid=!1),this.__currentElementProto=null},_findDefinitions:function(e){var t=e.parsedCssText;t=t.replace(/var\(\s*(--[^,]*),\s*(--[^)]*)\)/g,o),t=t.replace(u,i),e.cssText=t,":root"===e.selector&&(e.selector=":host > *")},_findApplications:function(e){e.cssText=l(e.cssText)},transformRule:function(e){this._findDefinitions(e),this._findApplications(e)},_getInitialValueForProperty:function(e){return this._measureElement||(this._measureElement=document.createElement("meta"),this._measureElement.style.all="initial",document.head.appendChild(this._measureElement)),window.getComputedStyle(this._measureElement).getPropertyValue(e)}};return m._boundTransformRule=m.transformRule.bind(m),m._boundFindDefinitions=m._findDefinitions.bind(m),m._boundFindApplications=m._findApplications.bind(m),m}(),function(){var e=Polymer.Base._prepElement,t=Polymer.Settings.useNativeShadow,n=Polymer.StyleUtil,r=Polymer.StyleTransformer,s=Polymer.StyleExtends,i=Polymer.ApplyShim,o=Polymer.Settings;Polymer.Base._addFeature({_prepElement:function(t){this._encapsulateStyle&&"shady"!==this.__cssBuild&&r.element(t,this.is,this._scopeCssViaAttr),e.call(this,t)},_prepStyles:function(){void 0===this._encapsulateStyle&&(this._encapsulateStyle=!t),t||(this._scopeStyle=n.applyStylePlaceHolder(this.is)),this.__cssBuild=n.cssBuildTypeForModule(this.is)},_prepShimStyles:function(){if(this._template){var e=n.isTargetedBuild(this.__cssBuild);if(o.useNativeCSSProperties&&"shadow"===this.__cssBuild&&e)return void(o.preserveStyleIncludes&&n.styleIncludesToTemplate(this._template));this._styles=this._styles||this._collectStyles(),o.useNativeCSSProperties&&!this.__cssBuild&&i.transform(this._styles,this);var s=o.useNativeCSSProperties&&e?this._styles.length&&this._styles[0].textContent.trim():r.elementStyles(this);this._prepStyleProperties(),!this._needsStyleProperties()&&s&&n.applyCss(s,this.is,t?this._template.content:null,this._scopeStyle)}else this._styles=[]},_collectStyles:function(){var e=[],t="",r=this.styleModules;if(r)for(var i,o=0,a=r.length;o=0)e=this.valueForProperties(e,t);else{var r=this,s=function(e,n,s,i){var o=r.valueForProperty(t[n],t);return o&&"initial"!==o?"apply-shim-inherit"===o&&(o="inherit"):o=r.valueForProperty(t[s]||s,t)||s,e+(o||"")+i};e=n.processVariableAndFallback(e,s)}return e&&e.trim()||""},valueForProperties:function(e,t){for(var n,r,s=e.split(";"),i=0;i\s*\*/,_checkRoot:function(e,t){return Boolean(t.match(this._rootSelector))||"html"===e&&t.indexOf("html")>-1},whenHostOrRootRule:function(e,t,n,s){if(t.propertyInfo||self.decorateRule(t),t.propertyInfo.properties){var o=e.is?r._calcHostScope(e.is,e.extends):"html",a=t.parsedSelector,l=this._checkRoot(o,a),c=!l&&0===a.indexOf(":host");if("shady"===(e.__cssBuild||n.__cssBuild)&&(l=a===o+" > *."+o||a.indexOf("html")>-1,c=!l&&0===a.indexOf(o)),l||c){var h=o;c&&(i.useNativeShadow&&!t.transformedSelector&&(t.transformedSelector=r._transformRuleCss(t,r._transformComplexSelector,e.is,o)),h=t.transformedSelector||t.parsedSelector),l&&"html"===o&&(h=t.transformedSelector||t.parsedSelector),s({selector:h,isHost:c,isRoot:l})}}},hostAndRootPropertiesForScope:function(e){var r={},s={},i=this;return n.forActiveRulesInStyles(e._styles,function(n,o){i.whenHostOrRootRule(e,n,o,function(o){var a=e._element||e;t.call(a,o.selector)&&(o.isHost?i.collectProperties(n,r):i.collectProperties(n,s))})}),{rootProps:s,hostProps:r}},transformStyles:function(e,t,n){var s=this,o=r._calcHostScope(e.is,e.extends),a=e.extends?"\\"+o.slice(0,-1)+"\\]":o,l=new RegExp(this.rx.HOST_PREFIX+a+this.rx.HOST_SUFFIX),c=this._elementKeyframeTransforms(e,n);return r.elementStyles(e,function(r){s.applyProperties(r,t),i.useNativeShadow||Polymer.StyleUtil.isKeyframesSelector(r)||!r.cssText||(s.applyKeyframeTransforms(r,c),s._scopeSelector(r,l,o,e._scopeCssViaAttr,n))})},_elementKeyframeTransforms:function(e,t){var n=e._styles._keyframes,r={};if(!i.useNativeShadow&&n)for(var s=0,o=n[s];s-1&&(o.textContent=a),n.applyStyle(o,null,e._scopeStyle)):a&&(o=n.applyCss(a,r,null,e._scopeStyle)),o&&(o._useCount=o._useCount||0,e._customStyle!=o&&o._useCount++,e._customStyle=o),o},mixinCustomStyle:function(e,t){var n;for(var r in t)((n=t[r])||0===n)&&(e[r]=n)},updateNativeStyleProperties:function(e,t){var n=e.__customStyleProperties;if(n)for(var r=0;rthis.MAX&&s.shift()},retrieve:function(e,t,n){var r=this.cache[e];if(r)for(var s,i=r.length-1;i>=0;i--)if(s=r[i],n===s.styles&&this._objectsEqual(t,s.keyValues))return s},clear:function(){this.cache={}},_objectsEqual:function(e,t){var n,r;for(var s in e)if(n=e[s],r=t[s],!("object"==typeof n&&n?this._objectsStrictlyEqual(n,r):n===r))return!1;return!Array.isArray(e)||e.length===t.length},_objectsStrictlyEqual:function(e,t){return this._objectsEqual(e,t)&&this._objectsEqual(t,e)}}}(),Polymer.StyleDefaults=function(){var e=Polymer.StyleProperties,t=Polymer.StyleCache,n=Polymer.Settings.useNativeCSSProperties;return{_styles:[],_properties:null,customStyle:{},_styleCache:new t,_element:Polymer.DomApi.wrap(document.documentElement),addStyle:function(e){this._styles.push(e),this._properties=null},get _styleProperties(){return this._properties||(e.decorateStyles(this._styles,this),this._styles._scopeStyleProperties=null,this._properties=e.hostAndRootPropertiesForScope(this).rootProps,e.mixinCustomStyle(this._properties,this.customStyle),e.reify(this._properties)),this._properties},hasStyleProperties:function(){return Boolean(this._properties)},_needsStyleProperties:function(){},_computeStyleProperties:function(){return this._styleProperties},updateStyles:function(t){this._properties=null,t&&Polymer.Base.mixin(this.customStyle,t),this._styleCache.clear() +;for(var r,s=0;s0&&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:!Polymer.Settings.suppressTemplateNotifications,readOnly:!0},initialCount:{type:Number,observer:"_initializeChunking"},targetFramerate:{type:Number,value:20},notifyDomChange:{type:Boolean},_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),Polymer.Settings.suppressTemplateNotifications&&!this.notifyDomChange||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 055f78334dc5f54ff652fc6261ecc9fc4edd133a..a55204f203c36e36624813e501c97257c6755fd0 100644 GIT binary patch delta 134602 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 z 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

t4xYv$VFW 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 delta 134057 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�@pU>E+*R+~YY8%Sf^vex|d~^#~99 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 I+FlL@02^bOy8r+H diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 0c428134dfb..19b903dfb7c 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 0c428134dfb6374b4a120cb729396242b4c2f2d7 +Subproject commit 19b903dfb7c940bfafdecc5407526647d0aed2f2 diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-automation.html b/homeassistant/components/frontend/www_static/panels/ha-panel-automation.html index 4da09363373..376d9b8a378 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-automation.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-automation.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-automation.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-automation.html.gz index 7d3cf0d815209a9b2ba44eb7514f268b69e3c4d1..051b7e0552a7065c41904a7bcd46576a865a0247 100644 GIT binary patch delta 26465 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%0DyCSp{J;4(|5X00g`f6a%WD0S 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 my!mqwbB diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-config.html b/homeassistant/components/frontend/www_static/panels/ha-panel-config.html index 9ba6338ce00..104b090ed61 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-config.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-config.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-config.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-config.html.gz index 2364c355d66f65be42c949cf3d6fdbd309d9f248..8e8ba12d1b4532597551ce2009b91bf186ce2a58 100644 GIT binary patch delta 13954 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 H3k(bZprk)_ delta 13950 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 JuKEH40{|J5QNI8H diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html index 6f501f7db26..236e0fb286a 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.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-event.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-event.html.gz index 1a8faa4f3e695ff5a79e906e02423c17a7070022..2f78956badfd8a3fe5ac4488af922636ad13de64 100644 GIT binary patch delta 2390 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 delta 2403 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 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 ed1ff9fe85d..aeab2aaf465 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 c76c9bc6de1a339afa24abd6beaa2b5f3af5bb4c..c479a26990fa287447a8722b88b4831855debd10 100644 GIT binary patch delta 23142 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 delta 23118 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 IFfuX#0C>W0@&Et; diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html index 6f03db94edf..75d9dfa9d6e 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.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-state.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-state.html.gz index 742f5eef9eef0b78a23e827bec24a7235641a3a5..e28e4ae8f301e798d009882fbd31708b939cd57a 100644 GIT binary patch delta 2657 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 Hfq?-4hAt5z diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-template.html b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-template.html index bb27f9a2d7d..c1be1953639 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-dev-template.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-template.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-template.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-dev-template.html.gz index 9c3063c0d6c27794f6ee9a0f5f60e4524a3f7b9b..d5877c44dc039c5abd0d54a552cf7154ad8ac25b 100644 GIT binary patch delta 10855 zcmZ1(xixZvLH(^W9!sVzNqdv=<^K9cHV+0CRqK=YTvr-)x-FLObz6Lqq47HZ)3V~f zzZxgK`1N(#v?aoJ6ZR~4dh6%$-P`}}EdKk8tI<)+HgDqR`7%I5fexblC; z{T3D9x}_iL{_f)VoDv@Qe@gDWZ6@+H)6-v?M@Bun`Rw_mDJ8Wxp4Q*&dzR|d{Z#SX zp<2hqPZ!qQy7=^ZrS_A~&eMzknKx^y=btS#Pj^}xd`R9Uc>ZHs+tb}|d?TNE zZqQd;UtY3!iNe8WmaVCdj-UHY;;r7RUNYxb*}Ht=<**;WbA^S6HL9K>_)INLV` zk4q~~C+t-YsQ7&JcCibe)9W9|wWH zjK_;=Ze2L2H@TQ8v_AKDj8%f?&G~*oYh+FD?o9jk>%#l|6T#c`r?U%uX3SEH^!!?UN=LF*&vWK~mX})In${kPPnD(b zA4q#e?&9Q4 z%w2qDCu?^-St)Af|5{!3uGnNR76(pip*n+>-kbA&O`gnR7Qh;EV%sI*AL$*eTmHCY z?y};{-8SQmZX374rSNZ0W`&2|f1ws;ZMI6?J9Mk(^$g)GU(?JLvN4Vu$_hj;c^Go9 z`?cew+vdfu4ZNd*4GfxjeYAg-t#C^oAvfO!|lnl|2`FA4`P<~i3q*Sa7*aw zMkebIp1-Cp%rICmo5NbZYM$_hWh-rtPRY`Z{vlNMNhDgy+uB3)sv7gIt1?sfXBFS* z_nf#v;8>%*%IqaIQAtxig>Jf=TIm@S`mt!2V(KTsPwzJ=9b7rbBgl5)k`SW_3mQ)H z)nD0prp!Bk>Shm~KfIfS)SiFXu+VVN>bp8EH|>0wmI@fnC_ExP!%(Tg^~0$g{%a0Q z)1H|m?Z4@;G(tPavu^$pho_B2yY@Y=t+^0UyCiUaVVLom%PiYZ%t_hR*zvL~Wb-24 z6h?!M=eap9R&JVG!aSAL+rX+QmBrhj<&#(E@e{}E`BFdH_q?}x`(jpHOv0QupVQSB z8Q#qI5{&)hFkgU+f8F87EB%;$7}*>Nz9#bjTVI6NMmw2Us~b-vXMX&||9#7w4?3}u z*H?G!ei;>%^zq22M@mx@Jpym#R;vF@KEM6t-HW=bn7nliL%n=n30>~)W~uPKE@Zzq zSkAtl%`G@!<=6UMdpcjVP1`d0o?5y0xAVK+$i^P~!S<_cdb_u_(4@oi&G8A>&TEL? z?Q)*^a-I2&NwML)J5LF0pY(E?Q>nqaw`~6Pi~YT&ovw=I>3(~BG4#4f-2&Cf%Twjd zrZPOqRh_h(ea1&C&I7-4Di0T473Gj~JYHYVHhbE=ZiA|&lJ4Rb7wd~;T*Y`-N5v+r zWnH{ZZdQ1hj6}#fvke#Ql24wHO}j07V1+Oi8%clvVrGG@V zTHN@>bwhG=OI|Nq;eOI;>3pkYKX#qqdupoRzjvyXM*7F#3!6p$soXF!fAroe_S)Id z=C9|Jg{t!wt(?70>QJgu^Rhpw^#?XNwu(H=>`E4}T%Mq=75iN~tg`Bj=iAq^yZ2fJ zWk){!rOuNgs2Ta-clIv_JGIDjQ>T2j`0nFY8~R2$?L?9D+k`2}6P`N8if`5l-}#Nz zz?IY0bE=%&!Ufga?oC?V^j3CW=>D=qt5DxL%G?WHr$}!sX55z<9VSq4{HSTGoLPOC z-*$t#ZBIqR-qs%VT$^)##hs%^jg5GB%nSY1p3?A+S@U1y)|BF>{V$JdZ@dt&u<-UF zxv5iImpC2d+tIeJv~Zz*T7rAX(jCW2_kRzlKF4a|;w3J)$$Fys%bn}5*j%XLx^YPM zS(x_SsoBA$f0s09JXonMFWB?sw$821to<3i$LeQUI)B$W5O>LahIzoF5)a0#jml3C z-;(56_u#+6Z#BE~-bb8jo%&jJ^Bnf%pH0@&R=4@@_%+4l z>EWU`mAl;wygqSMP26AoronlJ%WBz9rDtb&BQwfo|Gm}DX{Kr!?G^3Cm*szhY4sm_ zlY7Sxnw|WtQ~&&px$Ld0>In?WHyIP^Uu^zf6_!8!Kq14q9AzbjO!t|KUvjQj;GW-9 zwdtHq(%j2RKc_w_X1Lr~{ccS&i+sksDXR@`H|#rYE+SL0I$mqu>*=c{?)hz@5cV! zQ|wnr#BBd<`*l@K_O_$VrOqMF%Z2k6JU$uT#~nK{GIA$>%k9UnyG=C8R$mWq=u73; z(zky~}*(plm5lj1CYs^=fz&|>&;h@r@K z4)YW4<0tGCv)?qT<{ad^_+?+sgOyjM*(bV-s@!K_nXIU}CtLCF>RY#BuWq~gC0gYC zj?A394n2iOKYcr+@nYNCZ##>5_qXjl+a-S}c-3BW-G3&xxj&z0%bHrnH@7qF_NIDe z8>O>~x8C1a@P(ICen&LlrN7nOv&xx#L+xKLQR+^f*!w#1beQV1mzkBH!PTXYnD_+&pl0@24k6^X))Fz>;|oV z#pm}fw9U9QySgAI;ayA{|J~J3mcKju$xONY;&XP1`08+5%guqAAMP4U2>zOP?CGtS z{bl`UuI5_xTbw_vIWg*(`@<6to98?X{j9OlTwJ_w^R*hEU3E|Ob=S!yT>2_$9avf4 zJR!$y&ZK&y!|%TyVVieKTl91NzO9^RMfeIfNi2UJw2kq+0qd+Pn0|IGaPP@!+Bvbkw!&WRmI#Sis2b2;k&{C1cB{`GhN=Iv{}$;@6} zos*|h)z_+?94t{>AO0%k`?5V>-+f5cG+)sfx%%`s8PQa}=K8$N2?aYp>8(Gt_VJya zi#{Ft5?igq)w=CL6ziP}jvGClZheh0-MM|urRo#0dS05Yn(J3z30*Jq=G#$caTj&d z^)i1Zsb*fUlzkF@-S7RSoj)eqe+}!)+2j?ayDE08q5tX+`VSZKTO&=2t` zb8cULclGGizt>9jPLypgs;V#D)O_;)z4WEi{-yi;znrm9b^oy^z4Lxb1;4MtqF&aFL(m!Gw1h;TD{?R^`3=Fap$-ZW|DUz3DH>#wD# ztn$lTy4_#9>m6gY()OwDxtp>(L#+*jN^UIjim=i)EqEIy7=PUHu2`e>i<(_XQKo4-WX@L50Oy)Cq7x}{zHyJfGJ zZ1=gI*g7TT)f<5eJN)~&ZOdQge4lO9c#}0oz%Osk`Z=jZQ#SS{hqiArO9^03ozpn8 z?$*h?Q>A6z@2By5^nA-Zpz`*{zt8W3D%NuTe=M}3%HY(_e>)l2^EeU zH?LUy=y|Cl62o}Jd;PO*0Zx1Dp8IJ0V4U+wL6|Z3RnR{DTaD8-eowJ-H!E3~xbMj{ z>s!r-URuvRx~Tiib{12gYnnZ~^Z4rjSg*9<41T44;oG> z=29kubEmD?H+q-t@K?4B<5=`%*WSfJ$&0Q?h}imXyPGxPrNvrpBcFf(p4B1S>>RFt zvdQN&i7;W;ZR_sj_F&=n+w&{_u=ZxTA68!;gr2ple!Zb|GB3}qi@yx6pNj5i`XeYZ zv547nPUj`J3EPyvm+WtTZfI8=SifU2=V{*J-4{z<+N4BlWSFe!=v%d*W6(l-&Iw{Le*L-kEFzdyR1!dmsrRNKOO7$v> z@O}9HdUf=r|5sn@@7uMzNd8**{~y<%PL*D_{vW@2fA~B1iYGp0%#*(7t-B*3v|wFI zz5D(hQ7ad}lfIvR@$n(MCry4I?tc8i+hFE4@6RF@whN2Slm!$_m?*P<`47%hss?Wp z1ovHIoLL{onDL04%hI`a^7AJvdmp`({T-xmlj*um4#$i5W^JBhYbwN!wn7e>AN?Zw+E1ypV>k0AYhK-&q44&y zaE3}(-JdDfcy8=lx8by?TYKrtZ6Quewx8H=+~rW1kI5z1$)(zf+phhMK3NyA^&`94 z{iUqIwTo}%gf%^zR^pwOwm0;XmFTjX(#n}%4)C7ZopbS4tL5T|nh!0k&!S|~q|LbV zSI#raUf~pzJ8e?EbXKItR-s$RFRCWWxBbx&J2kb&*6iv7;W=zA=fim~n!5f!sP-Xk z>49s_8~$;vTE0<_HDc4oj;{PE4%f4M%=+$6E4SS!vVW4q9aZa#zpiaMlCnKC@b#n9 zyMFNZI!zTx$PGxT%#>}`oc(5%@+z6CV6o)}jpp}^_P+e>J%7D@R!_Zj*73HW)fThg zbO!#;yUW*PxpmH+n+I0NZg<#`#gcITUTIuPhzrBg3gt61=Ioxc!6|nGTkPFmaWN}y zJI-30HFc>_%EhNe>gLDxoEKSrtiX-L3y5Gx74$ysGQPx)YwYw@nDm z>9OnBC*l-_*w-XW*)r{;4n@5OPsv-XDmirRI3^_NeZW=*}ftb7d@ zt6gLAnch;SJtrikC+*oec#CtQFFFIu3yr^`==!|A`TH5_wzAY2e z=hlCUb+){};{)$~mt&WAFDl-}KF3g3`0M2p;r9fm_De3es+#%z&Ypu`kGfjjcz8Nq z;E3I4>#g-q)C+iu<^KPkmiJ&{4$zBq6S z>*cxyu8f!Yna!VU{%iX#FyGPN_?||-xuj;a@x-(0pF%#^+}94;mU3tMP5V@n{kp-o z-4@>8$+uLeAT;uoZgy^VuzqY%)1NfXCl@^!leZgB(g{4VEz~eFdih41Ya*)myB8Rr zSn5&c$r<$Ts-FA5`h%OMl%LzzX`}qEsb&f9UY!F@B5EHEmRJXGbUn~JYjx%On@pC! zHEjHuq-y_OQDdFg|N8DT7qi^N^NMF$zC7J>;$e2poi!ff%;g@}g7xME#~;e6*L0SW zd6_=#PajMDL&NFE_PL%o|M%t6cJAt!vo0OmHf}iHn3OIa?w?lsX6DuUq6NyI0}mPn zKDKtdZ#&^rbjHH+1gq=Y`Qnp`e$F?#xvIbRU#gu-&gLyO3DTDY{&imB|Df(?c4eov z>C7Vs{zp|Wyk($ck^zugVpZye;>)_Tiq?b`2W z=Gs14lq=u%v}NM0_JxOR#nfwJVmj_Nw7%Hz;JS#b?No!`(a~1ZuDj}ozWtMXdfoS1 zeg5^C{4y^;OTXE0VO8qljMisXwejoDOnRiryE{!i$5|&;W3i*)G0yo{+4(Eyh3 zs^s}Ot>sdL)ANU-`&R$yeR(?Kt;^4!#%sfjN}I3qoT^`;=A*2-^#=MDV45QgJY)1g$GA&4o!>su#9=z?isFmi&D2=S<9sVWlo?#-uI_VPoIhi zpOqBgQr)2!Tx{G_C33$0)eEuh4|lFSG;Q-CE&piwX>Wxbt-=L`HZk-!tc%#QLPPSd z&btk)FHWg!_$wqTRBvs5%3~5gljA$#yse7IA9qTg`L*rryPeCO-ljiuDL+4B?MKH& ze0Ogjt9D(={;{o9v+C74vBP^;`8db2m>lYydubKd=14F5Bbld)zjAY_@!AX3w7dzdpS1pS5%bT9 z!rQn)^5b>ORQB%MTf6?ut%Qty$-Ji&^l!=B)QZ3T?S$CT3+0YdIgxV<`YRubxjMLe zZoHWg^u$cz&*^LV;Yx>ex9yxVGa~9;XG8C#O_#cpHwLHrtXY=FcmH1L&a!m}?p`+h z5*U4O!nVNmdeV+pdNuT|KE1Fz{m#683;*OF``%ZcwmPT3=dPbNa$rbFidh*dT63lnBibCHPXSu##mv_nF@>fN0ONjz3g$j9BHyv z@w?@3rWwLqX;=7_g^y_Zra2m@t94BN^vKm@=4=JO)7;PQMNB*-oVrm|ao2=%&56v% z>Q^4!Y#`yzdxOPQuE%yg2To01V3ugl+@$+-<9x=4Q^cnH<>6Rv{PkwO z>RK){J%P?lhn3TMjyyK#YK!_cVRD~%isP1&luRS(!lx@QAD>ZgG^>IwQg4#smQ~a2 zjuyFfUv%+){>FWAqD{}%FP2)j3hd@&zvRBcZU3d-S$A$n*V&UX=^Z?R29kbXq$V3O z{kd7OhIztrPHWy3Om8NAVLoNDBw6a!OOI+fmWhoGTaJIW_)yA_HPu{Jug!|#sZ`%y zNyALz1BaGhp2+uLQtz`m1JjOVeYszsJr^+V$nkvAuWl@Rpw)VQb&1UD2CrRmhNmVy zlC3UY+~u_IK>c>lHjdwqeg`l8_Pb{LLXAg)NB1pswBWwN-a2ol!Z~LT@x>W=O*EN8Tkn>COr4?f0Kd1aSxTx`HtDV}v zihBvnNBta^K33zYUSt04(E>(kZ{9v}UWwnb{W>pIF*P}VSE*O=I?O5XJVS7DBH(nq^*uzU=YJm)_7=n0mOY#&b+m@HP~xSb@YmvKi!aCV~6 zEVn}8{_tE8-wsx_9Wuwce12Fe{1W6znK-YHOVB0cAUz|9lDK!%#`Rv~ISPwh1o-8gp(O@ezx(6IN~MJ|-!Ap}s@s(MDby*AGeovz!#F=~!AFDrK zw7JGuuThcz%9mHl>50OH8xD?%zl*tDIwY@LZ{axCv@>Y>q)ELZ9}K>IEm3@+5yqCp zC&0wld_lvL!(zsy0Co<>$txf2<+!D>?q$t7=9Y%%-7_6yLXx-5kYZ4L@G>b$K%7a= zJ=vdqLBq+Ovqd~71b8!K+}RFmB-k&y(8=2&QsDFIUA<=d)Eu8)^-~8{`UD-eoZF_> zV(g%HG326h>Nl(Jhi}&8I27EN&!+I7jd@LC!khrLXpVBlVWO9kx!s6GEQ9%*kqM*>U)1N{Ymks23aM&x))_mUi^ zV-l|zEUVdAESnnx8bcPUo4xK+c0CehzPOR_FxZc^%B?%OfN;>=~=ZA%XrriGDXlcSNe-|U!z3rY7<1eVI3IjokU zw&fbrtYnVTEJoc6a(;i*JiP2a%@&=!Nd4drPT|n#8>d7L&G)lWez9_+vzqRrydMyJs)r<`H}vb z50-5a$CdA&lV@A{_~Mn#*WtxaXIb#*u3RPyCHj|k>zE*n@mtC|7 zVXJp-NtnS`^Y7xBhJ=Q`res%Mj$bY%7Seqo`JXwjPTw$p-n#WiG#CscHvcba*ypsE zq2g_G$6udYuTJ$cIq(-As%UmCJ?xnhN!nZmBlLX&u;)tyO%1vBB&gl}1<_e^q zign&O#clJ)9GU0^8mnGrocQ~$c+pTbs39UXPATZ#a%IzSJ;1u;_s-v=(Jg9hP+uD`>a}( z%J56N@){OvOgGeTUlsUD_+pgcSsk9e>t1-yD&5AldD4B)BU;m&+IuhcEj%E}bYFgb z>UQb0P^q(bO3&=Mo^kxz9lK}OOxBuiPH23)z|Y%zTbAnjvx4as*k-`9M7aPrx<1CJSQO?|dz5qse-b!)4wl|uXPOggt-Zi8%`mWcB_2m2}R zo67uFvg==2CATbX$^ubV`v>Z$h0Fff#XY*AC6G7q^{%`CcYAJLqWSM$;Gnug}^au=;O$=GLgn*~T}k_eGh$^*jD#*U3be zE_SK4^X_KUE9~DId3f#0KRHk4W;IKNyKIYTO4;ma8hPSUPQ6}bX2RklSt?iB%@!Xx zR}`7!&}H(9PinsMmpj+aaM)K{cJBD*EEzdd(d=B-zqx0>yvci9WOnY0f@$z-*|e*# z9DKvy3cUU?Id}U7;mbYuEh>|K*e$P$`E~xq>!{bf1rvO3lv){NIkkzK{_`wZ$meT) zeEy94-|g@I%lVYL{&4%O`gaLtfyd_u?`(P3;}&n{ttDE%w)&g({$QPYmz_>=Ui&ky zn%WwFcMn`wzwwPPeaXE!$+pFJ4m`SjymxcK>%<4@0;_cN*I%-%zj}E6 zp7SBDwpZp)zNwmNf1^2m(ysGvtskS@ZEf03JI{W&G3Q)>>_daSE0*eboIm${&9u!5 zcDq?W{xzS)RBgJZLjUBiJzmj;@e%oz{9M+zRQ=?pHtpNwe}De-gc;^;x2;((+3?OTXJ3cWXuW8W+SQPI{u~_-3BQx0|M#E|Ru&@$OrW@$bLC zB+!+id11ZO@*jm2M^`XCT&flNz$j3=uWOxn_|li6<}9m1|H~J}b(NZDU4JZIrs2Er z{F=G1(~=_}F1M%edW~q)-fvG|%hxysMLx^l{Ad2z-9L`F zZ+T-I(ylr3;l1FEWB2IqkhWab@x7>-@i3Dte^L5 zzWv&%=~JF7MWh}m-m&%ZOE2a(X6)(i^Zx%z{uO2^`fBZue?OiyZhmvet}kT%wc~x3 z6Q6Euc8`maIlOUto4D$p4HkVV+WxyOAGNlw+7WeA-`4r$*0}se@l{WnDp&6Ft6duF zD&xQ5^3P!F6H5>8ixXF`s4vX9XgEKm@7dmpHwV7RpU69)RQ-Na{sF(7ACj+n4?UHw z{-!+pjIr&R$2Lb^E?lK`o6BTI$Of0T=t{k{aqF!sx3yF*;oB|OTzYN!vzIkuI1mkeoxpE29Y}l60P2UT0A4Fzb}ZjK6zzib6?TZ`i@mP zT8W{(N6$9+mR)q)5mi6w{tt7huDjC8`sO(dthXz=`fQlpZGD&Db`i;0>9H+lIo~3! z^Jee8o3Hs{xj$>!tBSQ-?9K%_{NP-Y`I>P}`VY5b7vGp&*|^|ov`pNt3LkN) z7Tkd>>$$z{{y;(PC0*%jJV z{_TLg`qSlaKF;p_vC;a?nbnLY;XfAc`oC#;*}5u&xc#4|=`zT(>iJncin?gKB1h+` z;ET+snHlCeQlZ8w7c4lA6rGtOa8N7u`tr8B8tffgJJ_tIM^-;pTlOU*FnOWQvmaMN zWFmWx#?)Wk-aT)pOxPFWg__GIyuB1soEa0!esk9p+0@lvKSoz=Uo?IC-VlLfJDXvW{WzlkMB5*fNzR*Y7N|a!Z&PtD)%l^~tqBzm2yQrt79BHik`> zUYsKNz3fS8$hV)9cli7G?Mgfs%oO!v$I0H4=O#tnSikI;U;X;+Z}MJopPuLG=lAKh z%LQw#?Z*mM6l`Nmj5qJKdwc1Yt6cKa5bw6Dx%w}8O_WKK;b^Cs(pMAb&D!wRkP2oDxPZ+9Im{7L(4HMiHrk0Ga|VcN+fpVDQ7KZd0O>p-Oa35 zVRy~7*^f@Xe&E!{iSaJoyG}hao}(#v=ds25SF`hHJ32^QPU%^Fc*+j0)==?h_51cc z;=jKBZD8@9N@?y13lF&UIEd)Rz3Q%9sK$7&BU`2|qEPyzalqA@QwLY*B+G7!v}WI< z|E(hAN$~{RmZf3K<3B%IwSDrWfBbhP?(Eq3gMYu%5A#@_I~V&mtkaHBy{WIL*8f*4 z@Xq@amu@;7+q-#dux$QGr?#@vRlJP%)6cJ|_YrCqNe)|8bfU&pX7imt+n;dYLhI~Wmr6k;{{1hDoaH}yTE*q$ z6~W*e^!JZGi3LiGjXA4g&BAV&{l3a(!MCc^abxkF`S0ZVnYoNZ@p5>y}$SJzZj2ap3H%6(W1CuM?;^RlDuL>GHQ5rrtfrtodt! z%1ySIAJuizTC)o*v%(V3e_-9y@noV~=ro}}ryCmPGWjwrz0-YH(BR(2>URYPlKpc^ zG~^Ea*zBV-bMGI9^A*;6`+8T0)kkk=_-mwTJ|(bPeafZ@+Wt~sSI>$qKIy$9`^=_~ znG(9YP6Q>-U7Hn=b|<^Z;M|42DY@zAzrA(rUp)8!)Ft~TBrcaSOz>fyeD~*+Dg1Ml zZeKdL{mp!H*NGd1C!F@%xHwTrJ(1l?!?(NTD9gb&@%!&JAKvQeFmEpVhbNAgQg=qj z)yMulbgDhFU`A@Q&VKgS@?zl^LRSke+)-pD@u}&d*^LQbnu~LdRQm&;P5;&~!y%++ zisw3psyE+`*iC%HH|Y&mhymlQMFuOjw=M`g86_2}n!PG~&9Yw#R|V^~PBAOLbz$dZ z*GBbl-u|txFGMhhR>hlIbl*!&5nTD;&xg&cE>29U7g(XVYH=HHYa^41$gB5G%1eSi z`W-LjnzPe}`)B8eI}cB++^14~^+lV$^s~2R(bCK0BlbA%Hn{1!G=Kj+moLXJPrtv# zNtvre%V12*I?@RmK&wcaXqnAF>b*g04Q7@^+2@^y&q|f!8 z_IANyK{Lz9BsH^>hlOs2Rz;ZXkjP{_xkqSj-vm?VH1{5H)hQgNO(pd!R$#m1Tf3@wZv0vHdFSDE8K)w97tU&DZu+r*LW#u}*R-J6_eM7k2mG_^ zzMrqD`OPx!SkanQvdX`k?X|=CJzH1l%dOfK`+BeG*@Fq0yDxt{Hc@)=qa`KNUPZg} z&6(={Ampf&+QOw7bM~BIWc6Av_qyKilGx*CJB;d1#b3K><>zuUNOm`8^o^ajOdj}h z+Js6)r5fH!oqy|;p3XzwOQHPh-(5{`Yr8M>DQ$Ym-1&8Xe#-8CzDy}fvY=;I__ICc z46I(W%{9W-s^>2c(D>y(^?vY*KYEP^#hzEM(^7w5va;&L>n_p5GLwsT@BFu)kH1od Jk$E)(0{}Ck59j~@ delta 10782 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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 0b22672f887..33e972c2349 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-map.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-map.html @@ -2,4 +2,4 @@ pt(this._mapPane,"leaflet-pan-anim");var e=this._getMapPanePos().subtract(t).round();this._panAnim.run(this._mapPane,e,i.duration||.25,i.easeLinearity)}else this._rawPanBy(t),this.fire("move").fire("moveend");return this},flyTo:function(t,i,e){function n(t){var i=t?-1:1,e=t?g:m,n=g*g-m*m+i*x*x*v*v,o=2*e*x*v,s=n/o,r=Math.sqrt(s*s+1)-s;return r<1e-9?-18:Math.log(r)}function o(t){return(Math.exp(t)-Math.exp(-t))/2}function s(t){return(Math.exp(t)+Math.exp(-t))/2}function r(t){return o(t)/s(t)}function a(t){return m*(s(w)/s(w+y*t))}function h(t){return m*(s(w)*r(w+y*t)-o(w))/x}function u(t){return 1-Math.pow(1-t,1.5)}function l(){var e=(Date.now()-L)/b,n=u(e)*P;e<=1?(this._flyToFrame=f(l,this),this._move(this.unproject(c.add(_.subtract(c).multiplyBy(h(n)/v)),p),this.getScaleZoom(m/a(n),p),{flyTo:!0})):this._move(t,i)._moveEnd(!0)}if(e=e||{},!1===e.animate||!Ki)return this.setView(t,i,e);this._stop();var c=this.project(this.getCenter()),_=this.project(t),d=this.getSize(),p=this._zoom;t=C(t),i=void 0===i?p:i;var m=Math.max(d.x,d.y),g=m*this.getZoomScale(p,i),v=_.distanceTo(c)||1,y=1.42,x=y*y,w=n(0),L=Date.now(),P=(n(1)-w)/y,b=e.duration?1e3*e.duration:1e3*P*.8;return this._moveStart(!0),l.call(this),this},flyToBounds:function(t,i){var e=this._getBoundsCenterZoom(t,i);return this.flyTo(e.center,e.zoom,i)},setMaxBounds:function(t){return t=z(t),t.isValid()?(this.options.maxBounds&&this.off("moveend",this._panInsideMaxBounds),this.options.maxBounds=t,this._loaded&&this._panInsideMaxBounds(),this.on("moveend",this._panInsideMaxBounds)):(this.options.maxBounds=null,this.off("moveend",this._panInsideMaxBounds))},setMinZoom:function(t){return this.options.minZoom=t,this._loaded&&this.getZoom()this.options.maxZoom?this.setZoom(t):this},panInsideBounds:function(t,i){this._enforcingBounds=!0;var e=this.getCenter(),n=this._limitCenter(e,this._zoom,z(t));return e.equals(n)||this.panTo(n,i),this._enforcingBounds=!1,this},invalidateSize:function(t){if(!this._loaded)return this;t=i({animate:!1,pan:!0},!0===t?{animate:!0}:t);var n=this.getSize();this._sizeChanged=!0,this._lastCenter=null;var o=this.getSize(),s=n.divideBy(2).round(),r=o.divideBy(2).round(),a=s.subtract(r);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(e(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:n,newSize:o})):this},stop:function(){return this.setZoom(this._limitZoom(this._zoom)),this.options.zoomSnap||this.fire("viewreset"),this._stop()},locate:function(t){if(t=this._locateOptions=i({timeout:1e4,watch:!1},t),!("geolocation"in navigator))return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var n=e(this._handleGeolocationResponse,this),o=e(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(n,o,t):navigator.geolocation.getCurrentPosition(n,o,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var i=t.code,e=t.message||(1===i?"permission denied":2===i?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:i,message:"Geolocation error: "+e+"."})},_handleGeolocationResponse:function(t){var i=t.coords.latitude,e=t.coords.longitude,n=new M(i,e),o=n.toBounds(t.coords.accuracy),s=this._locateOptions;if(s.setView){var r=this.getBoundsZoom(o);this.setView(n,s.maxZoom?Math.min(r,s.maxZoom):r)}var a={latlng:n,bounds:o,timestamp:t.timestamp};for(var h in t.coords)"number"==typeof t.coords[h]&&(a[h]=t.coords[h]);this.fire("locationfound",a)},addHandler:function(t,i){if(!i)return this;var e=this[t]=new i(this);return this._handlers.push(e),this.options[t]&&e.enable(),this},remove:function(){if(this._initEvents(!0),this._containerId!==this._container._leaflet_id)throw new Error("Map container is being reused by another instance");try{delete this._container._leaflet_id,delete this._containerId}catch(t){this._container._leaflet_id=void 0,this._containerId=void 0}ut(this._mapPane),this._clearControlPos&&this._clearControlPos(),this._clearHandlers(),this._loaded&&this.fire("unload");var t;for(t in this._layers)this._layers[t].remove();for(t in this._panes)ut(this._panes[t]);return this._layers=[],this._panes=[],delete this._mapPane,delete this._renderer,this},createPane:function(t,i){var e="leaflet-pane"+(t?" leaflet-"+t.replace("Pane","")+"-pane":""),n=ht("div",e,i||this._mapPane);return t&&(this._panes[t]=n),n},getCenter:function(){return this._checkIfLoaded(),this._lastCenter&&!this._moved()?this._lastCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds();return new T(this.unproject(t.getBottomLeft()),this.unproject(t.getTopRight()))},getMinZoom:function(){return void 0===this.options.minZoom?this._layersMinZoom||0:this.options.minZoom},getMaxZoom:function(){return void 0===this.options.maxZoom?void 0===this._layersMaxZoom?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,i,e){t=z(t),e=w(e||[0,0]);var n=this.getZoom()||0,o=this.getMinZoom(),s=this.getMaxZoom(),r=t.getNorthWest(),a=t.getSouthEast(),h=this.getSize().subtract(e),u=b(this.project(a,n),this.project(r,n)).getSize(),l=Ki?this.options.zoomSnap:1,c=h.x/u.x,_=h.y/u.y,d=i?Math.max(c,_):Math.min(c,_);return n=this.getScaleZoom(d,n),l&&(n=Math.round(n/(l/100))*(l/100),n=i?Math.ceil(n/l)*l:Math.floor(n/l)*l),Math.max(o,Math.min(s,n))},getSize:function(){return this._size&&!this._sizeChanged||(this._size=new x(this._container.clientWidth||0,this._container.clientHeight||0),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(t,i){var e=this._getTopLeftPoint(t,i);return new P(e,e.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._pixelOrigin},getPixelWorldBounds:function(t){return this.options.crs.getProjectedBounds(void 0===t?this.getZoom():t)},getPane:function(t){return"string"==typeof t?this._panes[t]:t},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t,i){var e=this.options.crs;return i=void 0===i?this._zoom:i,e.scale(t)/e.scale(i)},getScaleZoom:function(t,i){var e=this.options.crs;i=void 0===i?this._zoom:i;var n=e.zoom(t*e.scale(i));return isNaN(n)?1/0:n},project:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.latLngToPoint(C(t),i)},unproject:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.pointToLatLng(w(t),i)},layerPointToLatLng:function(t){var i=w(t).add(this.getPixelOrigin());return this.unproject(i)},latLngToLayerPoint:function(t){return this.project(C(t))._round()._subtract(this.getPixelOrigin())},wrapLatLng:function(t){return this.options.crs.wrapLatLng(C(t))},wrapLatLngBounds:function(t){return this.options.crs.wrapLatLngBounds(z(t))},distance:function(t,i){return this.options.crs.distance(C(t),C(i))},containerPointToLayerPoint:function(t){return w(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return w(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var i=this.containerPointToLayerPoint(w(t));return this.layerPointToLatLng(i)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(C(t)))},mouseEventToContainerPoint:function(t){return tt(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var i=this._container=rt(t);if(!i)throw new Error("Map container not found.");if(i._leaflet_id)throw new Error("Map container is already initialized.");V(i,"scroll",this._onScroll,this),this._containerId=n(i)},_initLayout:function(){var t=this._container;this._fadeAnimated=this.options.fadeAnimation&&Ki,pt(t,"leaflet-container"+(te?" leaflet-touch":"")+(ne?" leaflet-retina":"")+(Bi?" leaflet-oldie":"")+(Wi?" leaflet-safari":"")+(this._fadeAnimated?" leaflet-fade-anim":""));var i=at(t,"position");"absolute"!==i&&"relative"!==i&&"fixed"!==i&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._paneRenderers={},this._mapPane=this.createPane("mapPane",this._container),Lt(this._mapPane,new x(0,0)),this.createPane("tilePane"),this.createPane("shadowPane"),this.createPane("overlayPane"),this.createPane("markerPane"),this.createPane("tooltipPane"),this.createPane("popupPane"),this.options.markerZoomAnimation||(pt(t.markerPane,"leaflet-zoom-hide"),pt(t.shadowPane,"leaflet-zoom-hide"))},_resetView:function(t,i){Lt(this._mapPane,new x(0,0));var e=!this._loaded;this._loaded=!0,i=this._limitZoom(i),this.fire("viewprereset");var n=this._zoom!==i;this._moveStart(n)._move(t,i)._moveEnd(n),this.fire("viewreset"),e&&this.fire("load")},_moveStart:function(t){return t&&this.fire("zoomstart"),this.fire("movestart")},_move:function(t,i,e){void 0===i&&(i=this._zoom);var n=this._zoom!==i;return this._zoom=i,this._lastCenter=t,this._pixelOrigin=this._getNewPixelOrigin(t),(n||e&&e.pinch)&&this.fire("zoom",e),this.fire("move",e)},_moveEnd:function(t){return t&&this.fire("zoomend"),this.fire("moveend")},_stop:function(){return g(this._flyToFrame),this._panAnim&&this._panAnim.stop(),this},_rawPanBy:function(t){Lt(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_panInsideMaxBounds:function(){this._enforcingBounds||this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(t){this._targets={},this._targets[n(this._container)]=this;var i=t?G:V;i(this._container,"click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress",this._handleDOMEvent,this),this.options.trackResize&&i(window,"resize",this._onResize,this),Ki&&this.options.transform3DLimit&&(t?this.off:this.on).call(this,"moveend",this._onMoveEnd)},_onResize:function(){g(this._resizeRequest),this._resizeRequest=f(function(){this.invalidateSize({debounceMoveend:!0})},this)},_onScroll:function(){this._container.scrollTop=0,this._container.scrollLeft=0},_onMoveEnd:function(){var t=this._getMapPanePos();Math.max(Math.abs(t.x),Math.abs(t.y))>=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,i){for(var e,o=[],s="mouseout"===i||"mouseover"===i,r=t.target||t.srcElement,a=!1;r;){if((e=this._targets[n(r)])&&("click"===i||"preclick"===i)&&!t._simulated&&this._draggableMoved(e)){a=!0;break}if(e&&e.listens(i,!0)){if(s&&!ot(r,t))break;if(o.push(e),s)break}if(r===this._container)break;r=r.parentNode}return o.length||a||s||!ot(r,t)||(o=[this]),o},_handleDOMEvent:function(t){if(this._loaded&&!nt(t)){var i=t.type;"mousedown"!==i&&"keypress"!==i||zt(t.target||t.srcElement),this._fireDOMEvent(t,i)}},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,e,n){if("click"===t.type){var o=i({},t);o.type="preclick",this._fireDOMEvent(o,o.type,n)}if(!t._stopped&&(n=(n||[]).concat(this._findEventTargets(t,e)),n.length)){var s=n[0];"contextmenu"===e&&s.listens(e,!0)&&$(t);var r={originalEvent:t};if("keypress"!==t.type){var a=s.options&&"icon"in s.options;r.containerPoint=a?this.latLngToContainerPoint(s.getLatLng()):this.mouseEventToContainerPoint(t),r.layerPoint=this.containerPointToLayerPoint(r.containerPoint),r.latlng=a?s.getLatLng():this.layerPointToLatLng(r.layerPoint)}for(var h=0;h0?Math.round(t-i)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(i))},_limitZoom:function(t){var i=this.getMinZoom(),e=this.getMaxZoom(),n=Ki?this.options.zoomSnap:1;return n&&(t=Math.round(t/n)*n),Math.max(i,Math.min(e,t))},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){mt(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,i){var e=this._getCenterOffset(t)._floor();return!(!0!==(i&&i.animate)&&!this.getSize().contains(e)||(this.panBy(e,i),0))},_createAnimProxy:function(){var t=this._proxy=ht("div","leaflet-proxy leaflet-zoom-animated");this._panes.mapPane.appendChild(t),this.on("zoomanim",function(t){var i=Pe,e=this._proxy.style[i];wt(this._proxy,this.project(t.center,t.zoom),this.getZoomScale(t.zoom,1)),e===this._proxy.style[i]&&this._animatingZoom&&this._onZoomTransitionEnd()},this),this.on("load moveend",function(){var t=this.getCenter(),i=this.getZoom();wt(this._proxy,this.project(t,i),this.getZoomScale(i,1))},this),this._on("unload",this._destroyAnimProxy,this)},_destroyAnimProxy:function(){ut(this._proxy),delete this._proxy},_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,i,e){if(this._animatingZoom)return!0;if(e=e||{},!this._zoomAnimated||!1===e.animate||this._nothingToAnimate()||Math.abs(i-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(i),o=this._getCenterOffset(t)._divideBy(1-1/n);return!(!0!==e.animate&&!this.getSize().contains(o)||(f(function(){this._moveStart(!0)._animateZoom(t,i,!0)},this),0))},_animateZoom:function(t,i,n,o){n&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=i,pt(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:i,noUpdate:o}),setTimeout(e(this._onZoomTransitionEnd,this),250)},_onZoomTransitionEnd:function(){this._animatingZoom&&(mt(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom),f(function(){this._moveEnd(!0)},this))}}),ke=v.extend({options:{position:"topright"},initialize:function(t){l(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var i=this._map;return i&&i.removeControl(this),this.options.position=t,i&&i.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var i=this._container=this.onAdd(t),e=this.getPosition(),n=t._controlCorners[e];return pt(i,"leaflet-control"),-1!==e.indexOf("bottom")?n.insertBefore(i,n.firstChild):n.appendChild(i),this},remove:function(){return this._map?(ut(this._container),this.onRemove&&this.onRemove(this._map),this._map=null,this):this},_refocusOnMap:function(t){this._map&&t&&t.screenX>0&&t.screenY>0&&this._map.getContainer().focus()}}),Be=function(t){return new ke(t)};Se.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.remove(),this},_initControlPos:function(){function t(t,o){var s=e+t+" "+e+o;i[t+o]=ht("div",s,n)}var i=this._controlCorners={},e="leaflet-",n=this._controlContainer=ht("div",e+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){for(var t in this._controlCorners)ut(this._controlCorners[t]);ut(this._controlContainer),delete this._controlCorners,delete this._controlContainer}});var Ie=ke.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0,hideSingleBase:!1,sortLayers:!1,sortFunction:function(t,i,e,n){return e1,this._baseLayersList.style.display=t?"":"none"),this._separator.style.display=i&&t?"":"none",this},_onLayerChange:function(t){this._handlingClick||this._update();var i=this._getLayer(n(t.target)),e=i.overlay?"add"===t.type?"overlayadd":"overlayremove":"add"===t.type?"baselayerchange":null;e&&this._map.fire(e,i)},_createRadioElement:function(t,i){var e='",n=document.createElement("div");return n.innerHTML=e,n.firstChild},_addItem:function(t){var i,e=document.createElement("label"),o=this._map.hasLayer(t.layer);t.overlay?(i=document.createElement("input"),i.type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=o):i=this._createRadioElement("leaflet-base-layers",o),this._layerControlInputs.push(i),i.layerId=n(t.layer),V(i,"click",this._onInputClick,this);var s=document.createElement("span");s.innerHTML=" "+t.name;var r=document.createElement("div");return e.appendChild(r),r.appendChild(i),r.appendChild(s),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(e),this._checkDisabledLayers(),e},_onInputClick:function(){var t,i,e,n=this._layerControlInputs,o=[],s=[];this._handlingClick=!0;for(var r=n.length-1;r>=0;r--)t=n[r],i=this._getLayer(t.layerId).layer,e=this._map.hasLayer(i),t.checked&&!e?o.push(i):!t.checked&&e&&s.push(i);for(r=0;r=0;o--)t=e[o],i=this._getLayer(t.layerId).layer,t.disabled=void 0!==i.options.minZoom&&ni.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expand:function(){return this.expand()},_collapse:function(){return this.collapse()}}),Ae=function(t,i,e){return new Ie(t,i,e)},Oe=ke.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"−",zoomOutTitle:"Zoom out"},onAdd:function(t){var i="leaflet-control-zoom",e=ht("div",i+" leaflet-bar"),n=this.options;return this._zoomInButton=this._createButton(n.zoomInText,n.zoomInTitle,i+"-in",e,this._zoomIn),this._zoomOutButton=this._createButton(n.zoomOutText,n.zoomOutTitle,i+"-out",e,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),e},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,i,e,n,o){var s=ht("a",e,n);return s.innerHTML=t,s.href="#",s.title=i,s.setAttribute("role","button"),s.setAttribute("aria-label",i),J(s),V(s,"click",Q),V(s,"click",o,this),V(s,"click",this._refocusOnMap,this),s},_updateDisabled:function(){var t=this._map,i="leaflet-disabled";mt(this._zoomInButton,i),mt(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMinZoom())&&pt(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMaxZoom())&&pt(this._zoomInButton,i)}});Se.mergeOptions({zoomControl:!0}),Se.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new Oe,this.addControl(this.zoomControl))});var Re=function(t){return new Oe(t)},De=ke.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var i="leaflet-control-scale",e=ht("div",i),n=this.options;return this._addScales(n,i+"-line",e),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),e},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,i,e){t.metric&&(this._mScale=ht("div",i,e)),t.imperial&&(this._iScale=ht("div",i,e))},_update:function(){var t=this._map,i=t.getSize().y/2,e=t.distance(t.containerPointToLatLng([0,i]),t.containerPointToLatLng([this.options.maxWidth,i]));this._updateScales(e)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var i=this._getRoundNum(t),e=i<1e3?i+" m":i/1e3+" km";this._updateScale(this._mScale,e,i/t)},_updateImperial:function(t){var i,e,n,o=3.2808399*t;o>5280?(i=o/5280,e=this._getRoundNum(i),this._updateScale(this._iScale,e+" mi",e/i)):(n=this._getRoundNum(o),this._updateScale(this._iScale,n+" ft",n/o))},_updateScale:function(t,i,e){t.style.width=Math.round(this.options.maxWidth*e)+"px",t.innerHTML=i},_getRoundNum:function(t){var i=Math.pow(10,(Math.floor(t)+"").length-1),e=t/i;return e=e>=10?10:e>=5?5:e>=3?3:e>=2?2:1,i*e}}),Ne=function(t){return new De(t)},je=ke.extend({options:{position:"bottomright",prefix:'Leaflet'},initialize:function(t){l(this,t),this._attributions={}},onAdd:function(t){t.attributionControl=this,this._container=ht("div","leaflet-control-attribution"),J(this._container);for(var i in t._layers)t._layers[i].getAttribution&&this.addAttribution(t._layers[i].getAttribution());return this._update(),this._container},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):this},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):this},_update:function(){if(this._map){var t=[];for(var i in this._attributions)this._attributions[i]&&t.push(i);var e=[];this.options.prefix&&e.push(this.options.prefix),t.length&&e.push(t.join(", ")),this._container.innerHTML=e.join(" | ")}}});Se.mergeOptions({attributionControl:!0}),Se.addInitHook(function(){this.options.attributionControl&&(new je).addTo(this)});var We=function(t){return new je(t)};ke.Layers=Ie,ke.Zoom=Oe,ke.Scale=De,ke.Attribution=je,Be.layers=Ae,Be.zoom=Re,Be.scale=Ne,Be.attribution=We;var He,Fe=v.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled?this:(this._enabled=!0,this.addHooks(),this)},disable:function(){return this._enabled?(this._enabled=!1,this.removeHooks(),this):this},enabled:function(){return!!this._enabled}}),Ue={Events:xi},Ve=!1,Ge=te?"touchstart mousedown":"mousedown",qe={mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},Ke={mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"},Ye=wi.extend({options:{clickTolerance:3},initialize:function(t,i,e,n){l(this,n),this._element=t,this._dragStartTarget=i||t,this._preventOutline=e},enable:function(){this._enabled||(V(this._dragStartTarget,Ge,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(L.Draggable._dragging===this&&this.finishDrag(),G(this._dragStartTarget,Ge,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){if(!t._simulated&&this._enabled&&(this._moved=!1,!dt(this._element,"leaflet-zoom-anim")&&!(Ve||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(Ve=this,this._preventOutline&&zt(this._element),bt(),zi(),this._moving)))){this.fire("down");var i=t.touches?t.touches[0]:t;this._startPoint=new x(i.clientX,i.clientY),V(document,Ke[t.type],this._onMove,this),V(document,qe[t.type],this._onUp,this)}},_onMove:function(t){if(!t._simulated&&this._enabled){if(t.touches&&t.touches.length>1)return void(this._moved=!0);var i=t.touches&&1===t.touches.length?t.touches[0]:t,e=new x(i.clientX,i.clientY),n=e.subtract(this._startPoint);(n.x||n.y)&&(Math.abs(n.x)+Math.abs(n.y)1e-7;h++)i=s*Math.sin(a),i=Math.pow((1-i)/(1+i),s/2),u=Math.PI/2-2*Math.atan(r*i)-a,a+=u;return new M(a*e,t.x*e/n)}},tn=(Object.freeze||Object)({LonLat:$e,Mercator:Qe,SphericalMercator:bi}),en=i({},Pi,{code:"EPSG:3395",projection:Qe,transformation:function(){var t=.5/(Math.PI*Qe.R);return E(t,.5,-t,.5)}()}),nn=i({},Pi,{code:"EPSG:4326",projection:$e,transformation:E(1/180,1,-1/180,.5)}),on=i({},Li,{projection:$e,transformation:E(1,0,-1,0),scale:function(t){return Math.pow(2,t)},zoom:function(t){return Math.log(t)/Math.LN2},distance:function(t,i){var e=i.lng-t.lng,n=i.lat-t.lat;return Math.sqrt(e*e+n*n)},infinite:!0});Li.Earth=Pi,Li.EPSG3395=en,Li.EPSG3857=Zi,Li.EPSG900913=Ei,Li.EPSG4326=nn,Li.Simple=on;var sn=wi.extend({options:{pane:"overlayPane",attribution:null,bubblingMouseEvents:!0},addTo:function(t){return t.addLayer(this),this},remove:function(){return this.removeFrom(this._map||this._mapToAdd)},removeFrom:function(t){return t&&t.removeLayer(this),this},getPane:function(t){return this._map.getPane(t?this.options[t]||t:this.options.pane)},addInteractiveTarget:function(t){return this._map._targets[n(t)]=this,this}, removeInteractiveTarget:function(t){return delete this._map._targets[n(t)],this},getAttribution:function(){return this.options.attribution},_layerAdd:function(t){var i=t.target;if(i.hasLayer(this)){if(this._map=i,this._zoomAnimated=i._zoomAnimated,this.getEvents){var e=this.getEvents();i.on(e,this),this.once("remove",function(){i.off(e,this)},this)}this.onAdd(i),this.getAttribution&&i.attributionControl&&i.attributionControl.addAttribution(this.getAttribution()),this.fire("add"),i.fire("layeradd",{layer:this})}}});Se.include({addLayer:function(t){var i=n(t);return this._layers[i]?this:(this._layers[i]=t,t._mapToAdd=this,t.beforeAdd&&t.beforeAdd(this),this.whenReady(t._layerAdd,t),this)},removeLayer:function(t){var i=n(t);return this._layers[i]?(this._loaded&&t.onRemove(this),t.getAttribution&&this.attributionControl&&this.attributionControl.removeAttribution(t.getAttribution()),delete this._layers[i],this._loaded&&(this.fire("layerremove",{layer:t}),t.fire("remove")),t._map=t._mapToAdd=null,this):this},hasLayer:function(t){return!!t&&n(t)in this._layers},eachLayer:function(t,i){for(var e in this._layers)t.call(i,this._layers[e]);return this},_addLayers:function(t){t=t?pi(t)?t:[t]:[];for(var i=0,e=t.length;ithis._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()i)return r=(n-i)/e,this._map.layerPointToLatLng([s.x-r*(s.x-o.x),s.y-r*(s.y-o.y)])},getBounds:function(){return this._bounds},addLatLng:function(t,i){return i=i||this._defaultShape(),t=C(t),i.push(t),this._bounds.extend(t),this.redraw()},_setLatLngs:function(t){this._bounds=new T,this._latlngs=this._convertLatLngs(t)},_defaultShape:function(){return jt(this._latlngs)?this._latlngs:this._latlngs[0]},_convertLatLngs:function(t){for(var i=[],e=jt(t),n=0,o=t.length;n=2&&i[0]instanceof M&&i[0].equals(i[e-1])&&i.pop(),i},_setLatLngs:function(t){gn.prototype._setLatLngs.call(this,t),jt(this._latlngs)&&(this._latlngs=[this._latlngs])},_defaultShape:function(){return jt(this._latlngs[0])?this._latlngs[0]:this._latlngs[0][0]},_clipPoints:function(){var t=this._renderer._bounds,i=this.options.weight,e=new x(i,i);if(t=new P(t.min.subtract(e),t.max.add(e)),this._parts=[],this._pxBounds&&this._pxBounds.intersects(t)){if(this.options.noClip)return void(this._parts=this._rings);for(var n,o=0,s=this._rings.length;ot.y!=n.y>t.y&&t.x<(n.x-e.x)*(t.y-e.y)/(n.y-e.y)+e.x&&(u=!u);return u||gn.prototype._containsPoint.call(this,t,!0)}}),yn=hn.extend({initialize:function(t,i){l(this,i),this._layers={},t&&this.addData(t)},addData:function(t){var i,e,n,o=pi(t)?t:t.features;if(o){for(i=0,e=o.length;io?(i.height=o+"px",pt(t,s)):mt(t,s),this._containerWidth=this._container.offsetWidth},_animateZoom:function(t){var i=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center),e=this._getAnchor();Lt(this._container,i.add(e))},_adjustPan:function(){if(!(!this.options.autoPan||this._map._panAnim&&this._map._panAnim._inProgress)){var t=this._map,i=parseInt(at(this._container,"marginBottom"),10)||0,e=this._container.offsetHeight+i,n=this._containerWidth,o=new x(this._containerLeft,-e-this._containerBottom);o._add(Pt(this._container));var s=t.layerPointToContainerPoint(o),r=w(this.options.autoPanPadding),a=w(this.options.autoPanPaddingTopLeft||r),h=w(this.options.autoPanPaddingBottomRight||r),u=t.getSize(),l=0,c=0;s.x+n+h.x>u.x&&(l=s.x+n-u.x+h.x),s.x-l-a.x<0&&(l=s.x-a.x),s.y+e+h.y>u.y&&(c=s.y+e-u.y+h.y),s.y-c-a.y<0&&(c=s.y-a.y),(l||c)&&t.fire("autopanstart").panBy([l,c])}},_onCloseButtonClick:function(t){this._close(),Q(t)},_getAnchor:function(){return w(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}}),Mn=function(t,i){return new zn(t,i)};Se.mergeOptions({closePopupOnClick:!0}),Se.include({openPopup:function(t,i,e){return t instanceof zn||(t=new zn(e).setContent(t)),i&&t.setLatLng(i),this.hasLayer(t)?this:(this._popup&&this._popup.options.autoClose&&this.closePopup(),this._popup=t,this.addLayer(t))},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&this.removeLayer(t),this}}),sn.include({bindPopup:function(t,i){return t instanceof zn?(l(t,i),this._popup=t,t._source=this):(this._popup&&!i||(this._popup=new zn(i,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t,i){if(t instanceof sn||(i=t,t=this),t instanceof hn)for(var e in this._layers){t=this._layers[e];break}return i||(i=t.getCenter?t.getCenter():t.getLatLng()),this._popup&&this._map&&(this._popup._source=t,this._popup.update(),this._map.openPopup(this._popup,i)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(t){return this._popup&&(this._popup._map?this.closePopup():this.openPopup(t)),this},isPopupOpen:function(){return!!this._popup&&this._popup.isOpen()},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},getPopup:function(){return this._popup},_openPopup:function(t){var i=t.layer||t.target;if(this._popup&&this._map)return Q(t),i instanceof pn?void this.openPopup(t.layer||t.target,t.latlng):void(this._map.hasLayer(this._popup)&&this._popup._source===i?this.closePopup():this.openPopup(i,t.latlng))},_movePopup:function(t){this._popup.setLatLng(t.latlng)},_onKeyPress:function(t){13===t.originalEvent.keyCode&&this._openPopup(t)}});var Cn=Tn.extend({options:{pane:"tooltipPane",offset:[0,0],direction:"auto",permanent:!1,sticky:!1,interactive:!1,opacity:.9},onAdd:function(t){Tn.prototype.onAdd.call(this,t),this.setOpacity(this.options.opacity),t.fire("tooltipopen",{tooltip:this}),this._source&&this._source.fire("tooltipopen",{tooltip:this},!0)},onRemove:function(t){Tn.prototype.onRemove.call(this,t),t.fire("tooltipclose",{tooltip:this}),this._source&&this._source.fire("tooltipclose",{tooltip:this},!0)},getEvents:function(){var t=Tn.prototype.getEvents.call(this);return te&&!this.options.permanent&&(t.preclick=this._close),t},_close:function(){this._map&&this._map.closeTooltip(this)},_initLayout:function(){var t="leaflet-tooltip "+(this.options.className||"")+" leaflet-zoom-"+(this._zoomAnimated?"animated":"hide");this._contentNode=this._container=ht("div",t)},_updateLayout:function(){},_adjustPan:function(){},_setPosition:function(t){var i=this._map,e=this._container,n=i.latLngToContainerPoint(i.getCenter()),o=i.layerPointToContainerPoint(t),s=this.options.direction,r=e.offsetWidth,a=e.offsetHeight,h=w(this.options.offset),u=this._getAnchor();"top"===s?t=t.add(w(-r/2+h.x,-a+h.y+u.y,!0)):"bottom"===s?t=t.subtract(w(r/2-h.x,-h.y,!0)):"center"===s?t=t.subtract(w(r/2+h.x,a/2-u.y+h.y,!0)):"right"===s||"auto"===s&&o.xthis.options.maxZoom||en&&this._retainParent(o,s,r,n))},_retainChildren:function(t,i,e,n){for(var o=2*t;o<2*t+2;o++)for(var s=2*i;s<2*i+2;s++){var r=new x(o,s);r.z=e+1;var a=this._tileCoordsToKey(r),h=this._tiles[a];h&&h.active?h.retain=!0:(h&&h.loaded&&(h.retain=!0),e+1this.options.maxZoom||void 0!==this.options.minZoom&&o1)return void this._setView(t,e);for(var c=o.min.y;c<=o.max.y;c++)for(var _=o.min.x;_<=o.max.x;_++){var d=new x(_,c);d.z=this._tileZoom,this._isValidTile(d)&&(this._tiles[this._tileCoordsToKey(d)]||r.push(d))}if(r.sort(function(t,i){return t.distanceTo(s)-i.distanceTo(s)}),0!==r.length){this._loading||(this._loading=!0,this.fire("loading"));var p=document.createDocumentFragment();for(_=0;_e.max.x)||!i.wrapLat&&(t.ye.max.y))return!1}if(!this.options.bounds)return!0;var n=this._tileCoordsToBounds(t);return z(this.options.bounds).overlaps(n)},_keyToBounds:function(t){return this._tileCoordsToBounds(this._keyToTileCoords(t))},_tileCoordsToBounds:function(t){var i=this._map,e=this.getTileSize(),n=t.scaleBy(e),o=n.add(e),s=i.unproject(n,t.z),r=i.unproject(o,t.z),a=new T(s,r);return this.options.noWrap||i.wrapLatLngBounds(a),a},_tileCoordsToKey:function(t){return t.x+":"+t.y+":"+t.z},_keyToTileCoords:function(t){var i=t.split(":"),e=new x(+i[0],+i[1]);return e.z=+i[2],e},_removeTile:function(t){var i=this._tiles[t];i&&(ut(i.el),delete this._tiles[t],this.fire("tileunload",{tile:i.el,coords:this._keyToTileCoords(t)}))},_initTile:function(t){pt(t,"leaflet-tile");var i=this.getTileSize();t.style.width=i.x+"px",t.style.height=i.y+"px",t.onselectstart=r,t.onmousemove=r,Bi&&this.options.opacity<1&&vt(t,this.options.opacity),Oi&&!Ri&&(t.style.WebkitBackfaceVisibility="hidden")},_addTile:function(t,i){var n=this._getTilePos(t),o=this._tileCoordsToKey(t),s=this.createTile(this._wrapCoords(t),e(this._tileReady,this,t));this._initTile(s),this.createTile.length<2&&f(e(this._tileReady,this,t,null,s)),Lt(s,n),this._tiles[o]={el:s,coords:t,current:!0},i.appendChild(s),this.fire("tileloadstart",{tile:s,coords:t})},_tileReady:function(t,i,n){if(this._map){i&&this.fire("tileerror",{error:i,tile:n,coords:t});var o=this._tileCoordsToKey(t);(n=this._tiles[o])&&(n.loaded=+new Date,this._map._fadeAnimated?(vt(n.el,0),g(this._fadeFrame),this._fadeFrame=f(this._updateOpacity,this)):(n.active=!0,this._pruneTiles()),i||(pt(n.el,"leaflet-tile-loaded"),this.fire("tileload",{tile:n.el,coords:t})),this._noTilesToLoad()&&(this._loading=!1,this.fire("load"),Bi||!this._map._fadeAnimated?f(this._pruneTiles,this):setTimeout(e(this._pruneTiles,this),250)))}},_getTilePos:function(t){return t.scaleBy(this.getTileSize()).subtract(this._level.origin)},_wrapCoords:function(t){var i=new x(this._wrapX?s(t.x,this._wrapX):t.x,this._wrapY?s(t.y,this._wrapY):t.y);return i.z=t.z,i},_pxBoundsToTileRange:function(t){var i=this.getTileSize();return new P(t.min.unscaleBy(i).floor(),t.max.unscaleBy(i).ceil().subtract([1,1]))},_noTilesToLoad:function(){for(var t in this._tiles)if(!this._tiles[t].loaded)return!1;return!0}}),kn=Sn.extend({options:{minZoom:0,maxZoom:18,subdomains:"abc",errorTileUrl:"",zoomOffset:0,tms:!1,zoomReverse:!1,detectRetina:!1,crossOrigin:!1},initialize:function(t,i){this._url=t,i=l(this,i),i.detectRetina&&ne&&i.maxZoom>0&&(i.tileSize=Math.floor(i.tileSize/2),i.zoomReverse?(i.zoomOffset--,i.minZoom++):(i.zoomOffset++,i.maxZoom--),i.minZoom=Math.max(0,i.minZoom)),"string"==typeof i.subdomains&&(i.subdomains=i.subdomains.split("")),Oi||this.on("tileunload",this._onTileRemove)},setUrl:function(t,i){return this._url=t,i||this.redraw(),this},createTile:function(t,i){var n=document.createElement("img");return V(n,"load",e(this._tileOnLoad,this,i,n)),V(n,"error",e(this._tileOnError,this,i,n)),this.options.crossOrigin&&(n.crossOrigin=""),n.alt="",n.setAttribute("role","presentation"),n.src=this.getTileUrl(t),n},getTileUrl:function(t){var e={r:ne?"@2x":"",s:this._getSubdomain(t),x:t.x,y:t.y,z:this._getZoomForUrl()};if(this._map&&!this._map.options.crs.infinite){var n=this._globalTileRange.max.y-t.y;this.options.tms&&(e.y=n),e["-y"]=n}return _(this._url,i(e,this.options))},_tileOnLoad:function(t,i){Bi?setTimeout(e(t,this,null,i),0):t(null,i)},_tileOnError:function(t,i,e){var n=this.options.errorTileUrl;n&&i.src!==n&&(i.src=n),t(e,i)},_onTileRemove:function(t){t.tile.onload=null},_getZoomForUrl:function(){var t=this._tileZoom,i=this.options.maxZoom,e=this.options.zoomReverse,n=this.options.zoomOffset;return e&&(t=i-t),t+n},_getSubdomain:function(t){var i=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[i]},_abortLoading:function(){var t,i;for(t in this._tiles)this._tiles[t].coords.z!==this._tileZoom&&(i=this._tiles[t].el,i.onload=r,i.onerror=r,i.complete||(i.src=mi,ut(i)))}}),Bn=kn.extend({defaultWmsParams:{service:"WMS",request:"GetMap",layers:"",styles:"",format:"image/jpeg",transparent:!1,version:"1.1.1"},options:{crs:null,uppercase:!1},initialize:function(t,e){this._url=t;var n=i({},this.defaultWmsParams);for(var o in e)o in this.options||(n[o]=e[o]);e=l(this,e),n.width=n.height=e.tileSize*(e.detectRetina&&ne?2:1),this.wmsParams=n},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var i=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[i]=this._crs.code,kn.prototype.onAdd.call(this,t)},getTileUrl:function(t){var i=this._tileCoordsToBounds(t),e=this._crs.project(i.getNorthWest()),n=this._crs.project(i.getSouthEast()),o=(this._wmsVersion>=1.3&&this._crs===nn?[n.y,e.x,e.y,n.x]:[e.x,n.y,n.x,e.y]).join(","),s=kn.prototype.getTileUrl.call(this,t);return s+c(this.wmsParams,s,this.options.uppercase)+(this.options.uppercase?"&BBOX=":"&bbox=")+o},setParams:function(t,e){return i(this.wmsParams,t),e||this.redraw(),this}});kn.WMS=Bn,si.wms=ri;var In=sn.extend({options:{padding:.1},initialize:function(t){l(this,t),n(this),this._layers=this._layers||{}},onAdd:function(){this._container||(this._initContainer(),this._zoomAnimated&&pt(this._container,"leaflet-zoom-animated")),this.getPane().appendChild(this._container),this._update(),this.on("update",this._updatePaths,this)},onRemove:function(){this.off("update",this._updatePaths,this),this._destroyContainer()},getEvents:function(){var t={viewreset:this._reset,zoom:this._onZoom,moveend:this._update,zoomend:this._onZoomEnd};return this._zoomAnimated&&(t.zoomanim=this._onAnimZoom),t},_onAnimZoom:function(t){this._updateTransform(t.center,t.zoom)},_onZoom:function(){this._updateTransform(this._map.getCenter(),this._map.getZoom())},_updateTransform:function(t,i){var e=this._map.getZoomScale(i,this._zoom),n=Pt(this._container),o=this._map.getSize().multiplyBy(.5+this.options.padding),s=this._map.project(this._center,i),r=this._map.project(t,i),a=r.subtract(s),h=o.multiplyBy(-e).add(n).add(o).subtract(a);Ki?wt(this._container,h,e):Lt(this._container,h)},_reset:function(){this._update(),this._updateTransform(this._center,this._zoom);for(var t in this._layers)this._layers[t]._reset()},_onZoomEnd:function(){for(var t in this._layers)this._layers[t]._project()},_updatePaths:function(){for(var t in this._layers)this._layers[t]._update()},_update:function(){var t=this.options.padding,i=this._map.getSize(),e=this._map.containerPointToLayerPoint(i.multiplyBy(-t)).round();this._bounds=new P(e,e.add(i.multiplyBy(1+2*t)).round()),this._center=this._map.getCenter(),this._zoom=this._map.getZoom()}}),An=In.extend({getEvents:function(){var t=In.prototype.getEvents.call(this);return t.viewprereset=this._onViewPreReset,t},_onViewPreReset:function(){this._postponeUpdatePaths=!0},onAdd:function(){In.prototype.onAdd.call(this),this._draw()},_initContainer:function(){var t=this._container=document.createElement("canvas");V(t,"mousemove",o(this._onMouseMove,32,this),this),V(t,"click dblclick mousedown mouseup contextmenu",this._onClick,this),V(t,"mouseout",this._handleMouseOut,this),this._ctx=t.getContext("2d")},_destroyContainer:function(){delete this._ctx,ut(this._container),G(this._container),delete this._container},_updatePaths:function(){if(!this._postponeUpdatePaths){var t;this._redrawBounds=null;for(var i in this._layers)t=this._layers[i],t._update();this._redraw()}},_update:function(){if(!this._map._animatingZoom||!this._bounds){this._drawnLayers={},In.prototype._update.call(this);var t=this._bounds,i=this._container,e=t.getSize(),n=ne?2:1;Lt(i,t.min),i.width=n*e.x,i.height=n*e.y,i.style.width=e.x+"px",i.style.height=e.y+"px",ne&&this._ctx.scale(2,2),this._ctx.translate(-t.min.x,-t.min.y),this.fire("update")}},_reset:function(){In.prototype._reset.call(this),this._postponeUpdatePaths&&(this._postponeUpdatePaths=!1,this._updatePaths())},_initPath:function(t){this._updateDashArray(t),this._layers[n(t)]=t;var i=t._order={layer:t,prev:this._drawLast,next:null};this._drawLast&&(this._drawLast.next=i),this._drawLast=i,this._drawFirst=this._drawFirst||this._drawLast},_addPath:function(t){this._requestRedraw(t)},_removePath:function(t){var i=t._order,e=i.next,n=i.prev;e?e.prev=n:this._drawLast=n,n?n.next=e:this._drawFirst=e,delete t._order,delete this._layers[L.stamp(t)],this._requestRedraw(t)},_updatePath:function(t){this._extendRedrawBounds(t),t._project(),t._update(),this._requestRedraw(t)},_updateStyle:function(t){this._updateDashArray(t),this._requestRedraw(t)},_updateDashArray:function(t){if(t.options.dashArray){var i,e=t.options.dashArray.split(","),n=[];for(i=0;i')}}catch(t){return function(t){return document.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),Rn={_initContainer:function(){this._container=ht("div","leaflet-vml-container")},_update:function(){this._map._animatingZoom||(In.prototype._update.call(this),this.fire("update"))},_initPath:function(t){var i=t._container=On("shape");pt(i,"leaflet-vml-shape "+(this.options.className||"")),i.coordsize="1 1",t._path=On("path"),i.appendChild(t._path),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){var i=t._container;this._container.appendChild(i),t.options.interactive&&t.addInteractiveTarget(i)},_removePath:function(t){var i=t._container;ut(i),t.removeInteractiveTarget(i),delete this._layers[n(t)]},_updateStyle:function(t){var i=t._stroke,e=t._fill,n=t.options,o=t._container;o.stroked=!!n.stroke,o.filled=!!n.fill,n.stroke?(i||(i=t._stroke=On("stroke")),o.appendChild(i),i.weight=n.weight+"px",i.color=n.color,i.opacity=n.opacity,n.dashArray?i.dashStyle=pi(n.dashArray)?n.dashArray.join(" "):n.dashArray.replace(/( *, *)/g," "):i.dashStyle="",i.endcap=n.lineCap.replace("butt","flat"),i.joinstyle=n.lineJoin):i&&(o.removeChild(i),t._stroke=null),n.fill?(e||(e=t._fill=On("fill")),o.appendChild(e),e.color=n.fillColor||n.color,e.opacity=n.fillOpacity):e&&(o.removeChild(e),t._fill=null)},_updateCircle:function(t){var i=t._point.round(),e=Math.round(t._radius),n=Math.round(t._radiusY||e);this._setPath(t,t._empty()?"M0 0":"AL "+i.x+","+i.y+" "+e+","+n+" 0,23592600")},_setPath:function(t,i){t._path.v=i},_bringToFront:function(t){ct(t._container)},_bringToBack:function(t){_t(t._container)}},Dn=re?On:S,Nn=In.extend({getEvents:function(){var t=In.prototype.getEvents.call(this);return t.zoomstart=this._onZoomStart,t},_initContainer:function(){this._container=Dn("svg"),this._container.setAttribute("pointer-events","none"),this._rootGroup=Dn("g"),this._container.appendChild(this._rootGroup)},_destroyContainer:function(){ut(this._container),G(this._container),delete this._container,delete this._rootGroup},_onZoomStart:function(){this._update()},_update:function(){if(!this._map._animatingZoom||!this._bounds){In.prototype._update.call(this);var t=this._bounds,i=t.getSize(),e=this._container;this._svgSize&&this._svgSize.equals(i)||(this._svgSize=i,e.setAttribute("width",i.x),e.setAttribute("height",i.y)),Lt(e,t.min),e.setAttribute("viewBox",[t.min.x,t.min.y,i.x,i.y].join(" ")),this.fire("update")}},_initPath:function(t){var i=t._path=Dn("path");t.options.className&&pt(i,t.options.className),t.options.interactive&&pt(i,"leaflet-interactive"),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){this._rootGroup||this._initContainer(),this._rootGroup.appendChild(t._path),t.addInteractiveTarget(t._path)},_removePath:function(t){ut(t._path),t.removeInteractiveTarget(t._path),delete this._layers[n(t)]},_updatePath:function(t){t._project(),t._update()},_updateStyle:function(t){var i=t._path,e=t.options;i&&(e.stroke?(i.setAttribute("stroke",e.color),i.setAttribute("stroke-opacity",e.opacity),i.setAttribute("stroke-width",e.weight),i.setAttribute("stroke-linecap",e.lineCap),i.setAttribute("stroke-linejoin",e.lineJoin),e.dashArray?i.setAttribute("stroke-dasharray",e.dashArray):i.removeAttribute("stroke-dasharray"),e.dashOffset?i.setAttribute("stroke-dashoffset",e.dashOffset):i.removeAttribute("stroke-dashoffset")):i.setAttribute("stroke","none"),e.fill?(i.setAttribute("fill",e.fillColor||e.color),i.setAttribute("fill-opacity",e.fillOpacity),i.setAttribute("fill-rule",e.fillRule||"evenodd")):i.setAttribute("fill","none"))},_updatePoly:function(t,i){this._setPath(t,k(t._parts,i))},_updateCircle:function(t){var i=t._point,e=t._radius,n=t._radiusY||e,o="a"+e+","+n+" 0 1,0 ",s=t._empty()?"M0 0":"M"+(i.x-e)+","+i.y+o+2*e+",0 "+o+2*-e+",0 ";this._setPath(t,s)},_setPath:function(t,i){t._path.setAttribute("d",i)},_bringToFront:function(t){ct(t._path)},_bringToBack:function(t){_t(t._path)}});re&&Nn.include(Rn),Se.include({getRenderer:function(t){var i=t.options.renderer||this._getPaneRenderer(t.options.pane)||this.options.renderer||this._renderer;return i||(i=this._renderer=this.options.preferCanvas&&ai()||hi()),this.hasLayer(i)||this.addLayer(i),i},_getPaneRenderer:function(t){if("overlayPane"===t||void 0===t)return!1;var i=this._paneRenderers[t];return void 0===i&&(i=Nn&&hi({pane:t})||An&&ai({pane:t}),this._paneRenderers[t]=i),i}});var jn=vn.extend({initialize:function(t,i){vn.prototype.initialize.call(this,this._boundsToLatLngs(t),i)},setBounds:function(t){return this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=z(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}});Nn.create=Dn,Nn.pointsToPath=k,yn.geometryToLayer=Kt,yn.coordsToLatLng=Yt,yn.coordsToLatLngs=Xt,yn.latLngToCoords=Jt,yn.latLngsToCoords=$t,yn.getFeature=Qt,yn.asFeature=ti,Se.mergeOptions({boxZoom:!0});var Wn=Fe.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._resetStateTimeout=0,t.on("unload",this._destroy,this)},addHooks:function(){V(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){G(this._container,"mousedown",this._onMouseDown,this)},moved:function(){return this._moved},_destroy:function(){ut(this._pane),delete this._pane},_resetState:function(){this._resetStateTimeout=0,this._moved=!1},_clearDeferredResetState:function(){0!==this._resetStateTimeout&&(clearTimeout(this._resetStateTimeout),this._resetStateTimeout=0)},_onMouseDown:function(t){return!(!t.shiftKey||1!==t.which&&1!==t.button)&&(this._clearDeferredResetState(),this._resetState(),zi(),bt(),this._startPoint=this._map.mouseEventToContainerPoint(t),void V(document,{contextmenu:Q,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this))},_onMouseMove:function(t){this._moved||(this._moved=!0,this._box=ht("div","leaflet-zoom-box",this._container),pt(this._container,"leaflet-crosshair"),this._map.fire("boxzoomstart")),this._point=this._map.mouseEventToContainerPoint(t);var i=new P(this._point,this._startPoint),e=i.getSize();Lt(this._box,i.min),this._box.style.width=e.x+"px",this._box.style.height=e.y+"px"},_finish:function(){this._moved&&(ut(this._box),mt(this._container,"leaflet-crosshair")),Mi(),Tt(),G(document,{contextmenu:Q,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseUp:function(t){if((1===t.which||1===t.button)&&(this._finish(),this._moved)){this._clearDeferredResetState(),this._resetStateTimeout=setTimeout(e(this._resetState,this),0);var i=new T(this._map.containerPointToLatLng(this._startPoint),this._map.containerPointToLatLng(this._point));this._map.fitBounds(i).fire("boxzoomend",{boxZoomBounds:i})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}});Se.addInitHook("addHandler","boxZoom",Wn),Se.mergeOptions({doubleClickZoom:!0});var Hn=Fe.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var i=this._map,e=i.getZoom(),n=i.options.zoomDelta,o=t.originalEvent.shiftKey?e-n:e+n;"center"===i.options.doubleClickZoom?i.setZoom(o):i.setZoomAround(t.containerPoint,o)}});Se.addInitHook("addHandler","doubleClickZoom",Hn),Se.mergeOptions({dragging:!0,inertia:!Ri,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,easeLinearity:.2,worldCopyJump:!1,maxBoundsViscosity:0});var Fn=Fe.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new Ye(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),this._draggable.on("predrag",this._onPreDragLimit,this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDragWrap,this),t.on("zoomend",this._onZoomEnd,this),t.whenReady(this._onZoomEnd,this))}pt(this._map._container,"leaflet-grab leaflet-touch-drag"),this._draggable.enable(),this._positions=[],this._times=[]},removeHooks:function(){mt(this._map._container,"leaflet-grab"),mt(this._map._container,"leaflet-touch-drag"),this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},moving:function(){return this._draggable&&this._draggable._moving},_onDragStart:function(){var t=this._map;if(t._stop(),this._map.options.maxBounds&&this._map.options.maxBoundsViscosity){var i=z(this._map.options.maxBounds);this._offsetLimit=b(this._map.latLngToContainerPoint(i.getNorthWest()).multiplyBy(-1),this._map.latLngToContainerPoint(i.getSouthEast()).multiplyBy(-1).add(this._map.getSize())),this._viscosity=Math.min(1,Math.max(0,this._map.options.maxBoundsViscosity))}else this._offsetLimit=null;t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(t){if(this._map.options.inertia){var i=this._lastTime=+new Date,e=this._lastPos=this._draggable._absPos||this._draggable._newPos;this._positions.push(e),this._times.push(i),i-this._times[0]>50&&(this._positions.shift(),this._times.shift())}this._map.fire("move",t).fire("drag",t)},_onZoomEnd:function(){var t=this._map.getSize().divideBy(2),i=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=i.subtract(t).x,this._worldWidth=this._map.getPixelWorldBounds().getSize().x},_viscousLimit:function(t,i){return t-(t-i)*this._viscosity},_onPreDragLimit:function(){if(this._viscosity&&this._offsetLimit){var t=this._draggable._newPos.subtract(this._draggable._startPos),i=this._offsetLimit;t.xi.max.x&&(t.x=this._viscousLimit(t.x,i.max.x)),t.y>i.max.y&&(t.y=this._viscousLimit(t.y,i.max.y)),this._draggable._newPos=this._draggable._startPos.add(t)}},_onPreDragWrap:function(){ -var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)0?s:-s))-i;this._delta=0,this._startTime=null,r&&("center"===t.options.scrollWheelZoom?t.setZoom(i+r):t.setZoomAround(this._lastMousePos,i+r))}});Se.addInitHook("addHandler","scrollWheelZoom",Vn),Se.mergeOptions({tap:!0,tapTolerance:15});var Gn=Fe.extend({addHooks:function(){V(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){G(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if($(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new x(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&pt(n,"leaflet-active"),this._holdTimeout=setTimeout(e(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),this._simulateEvent("mousedown",i),V(document,{touchmove:this._onMove,touchend:this._onUp},this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),G(document,{touchmove:this._onMove,touchend:this._onUp},this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],e=i.target;e&&e.tagName&&"a"===e.tagName.toLowerCase()&&mt(e,"leaflet-active"),this._simulateEvent("mouseup",i),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var i=t.touches[0];this._newPos=new x(i.clientX,i.clientY),this._simulateEvent("mousemove",i)},_simulateEvent:function(t,i){var e=document.createEvent("MouseEvents");e._simulated=!0,i.target._simulatedClick=!0,e.initMouseEvent(t,!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),i.target.dispatchEvent(e)}});te&&!Qi&&Se.addInitHook("addHandler","tap",Gn),Se.mergeOptions({touchZoom:te&&!Ri,bounceAtZoomLimits:!0});var qn=Fe.extend({addHooks:function(){pt(this._map._container,"leaflet-touch-zoom"),V(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){mt(this._map._container,"leaflet-touch-zoom"),G(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var e=i.mouseEventToContainerPoint(t.touches[0]),n=i.mouseEventToContainerPoint(t.touches[1]);this._centerPoint=i.getSize()._divideBy(2),this._startLatLng=i.containerPointToLatLng(this._centerPoint),"center"!==i.options.touchZoom&&(this._pinchStartLatLng=i.containerPointToLatLng(e.add(n)._divideBy(2))),this._startDist=e.distanceTo(n),this._startZoom=i.getZoom(),this._moved=!1,this._zooming=!0,i._stop(),V(document,"touchmove",this._onTouchMove,this),V(document,"touchend",this._onTouchEnd,this),$(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length&&this._zooming){var i=this._map,n=i.mouseEventToContainerPoint(t.touches[0]),o=i.mouseEventToContainerPoint(t.touches[1]),s=n.distanceTo(o)/this._startDist;if(this._zoom=i.getScaleZoom(s,this._startZoom),!i.options.bounceAtZoomLimits&&(this._zoomi.getMaxZoom()&&s>1)&&(this._zoom=i._limitZoom(this._zoom)),"center"===i.options.touchZoom){if(this._center=this._startLatLng,1===s)return}else{var r=n._add(o)._divideBy(2)._subtract(this._centerPoint);if(1===s&&0===r.x&&0===r.y)return;this._center=i.unproject(i.project(this._pinchStartLatLng,this._zoom).subtract(r),this._zoom)}this._moved||(i._moveStart(!0),this._moved=!0),g(this._animRequest);var a=e(i._move,i,this._center,this._zoom,{pinch:!0,round:!1});this._animRequest=f(a,this,!0),$(t)}},_onTouchEnd:function(){return this._moved&&this._zooming?(this._zooming=!1,g(this._animRequest),G(document,"touchmove",this._onTouchMove),G(document,"touchend",this._onTouchEnd),void(this._map.options.zoomAnimation?this._map._animateZoom(this._center,this._map._limitZoom(this._zoom),!0,this._map.options.zoomSnap):this._map._resetView(this._center,this._map._limitZoom(this._zoom)))):void(this._zooming=!1)}});Se.addInitHook("addHandler","touchZoom",qn),Se.BoxZoom=Wn,Se.DoubleClickZoom=Hn,Se.Drag=Fn,Se.Keyboard=Un,Se.ScrollWheelZoom=Vn,Se.Tap=Gn,Se.TouchZoom=qn;var Kn=window.L;window.L=t,t.version="1.1.0",t.noConflict=li,t.Control=ke,t.control=Be,t.Browser=ae,t.Evented=wi,t.Mixin=Ue,t.Util=yi,t.Class=v,t.Handler=Fe,t.extend=i,t.bind=e,t.stamp=n,t.setOptions=l,t.DomEvent=Le,t.DomUtil=Ze,t.PosAnimation=Ee,t.Draggable=Ye,t.LineUtil=Xe,t.PolyUtil=Je,t.Point=x,t.point=w,t.Bounds=P,t.bounds=b,t.Transformation=Z,t.transformation=E,t.Projection=tn,t.LatLng=M,t.latLng=C,t.LatLngBounds=T,t.latLngBounds=z,t.CRS=Li,t.GeoJSON=yn,t.geoJSON=ii,t.geoJson=wn,t.Layer=sn,t.LayerGroup=rn,t.layerGroup=an,t.FeatureGroup=hn,t.featureGroup=un,t.ImageOverlay=Ln,t.imageOverlay=Pn,t.VideoOverlay=bn,t.videoOverlay=ei,t.DivOverlay=Tn,t.Popup=zn,t.popup=Mn,t.Tooltip=Cn,t.tooltip=Zn,t.Icon=ln,t.icon=Ht,t.DivIcon=En,t.divIcon=ni,t.Marker=dn,t.marker=Ft,t.TileLayer=kn,t.tileLayer=si,t.GridLayer=Sn,t.gridLayer=oi,t.SVG=Nn,t.svg=hi,t.Renderer=In,t.Canvas=An,t.canvas=ai,t.Path=pn,t.CircleMarker=mn,t.circleMarker=Ut,t.Circle=fn,t.circle=Vt,t.Polyline=gn,t.polyline=Gt,t.Polygon=vn,t.polygon=qt,t.Rectangle=jn,t.rectangle=ui,t.Map=Se,t.map=Ct}) \ No newline at end of file +var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)0?s:-s))-i;this._delta=0,this._startTime=null,r&&("center"===t.options.scrollWheelZoom?t.setZoom(i+r):t.setZoomAround(this._lastMousePos,i+r))}});Se.addInitHook("addHandler","scrollWheelZoom",Vn),Se.mergeOptions({tap:!0,tapTolerance:15});var Gn=Fe.extend({addHooks:function(){V(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){G(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if($(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new x(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&pt(n,"leaflet-active"),this._holdTimeout=setTimeout(e(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),this._simulateEvent("mousedown",i),V(document,{touchmove:this._onMove,touchend:this._onUp},this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),G(document,{touchmove:this._onMove,touchend:this._onUp},this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],e=i.target;e&&e.tagName&&"a"===e.tagName.toLowerCase()&&mt(e,"leaflet-active"),this._simulateEvent("mouseup",i),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var i=t.touches[0];this._newPos=new x(i.clientX,i.clientY),this._simulateEvent("mousemove",i)},_simulateEvent:function(t,i){var e=document.createEvent("MouseEvents");e._simulated=!0,i.target._simulatedClick=!0,e.initMouseEvent(t,!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),i.target.dispatchEvent(e)}});te&&!Qi&&Se.addInitHook("addHandler","tap",Gn),Se.mergeOptions({touchZoom:te&&!Ri,bounceAtZoomLimits:!0});var qn=Fe.extend({addHooks:function(){pt(this._map._container,"leaflet-touch-zoom"),V(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){mt(this._map._container,"leaflet-touch-zoom"),G(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var e=i.mouseEventToContainerPoint(t.touches[0]),n=i.mouseEventToContainerPoint(t.touches[1]);this._centerPoint=i.getSize()._divideBy(2),this._startLatLng=i.containerPointToLatLng(this._centerPoint),"center"!==i.options.touchZoom&&(this._pinchStartLatLng=i.containerPointToLatLng(e.add(n)._divideBy(2))),this._startDist=e.distanceTo(n),this._startZoom=i.getZoom(),this._moved=!1,this._zooming=!0,i._stop(),V(document,"touchmove",this._onTouchMove,this),V(document,"touchend",this._onTouchEnd,this),$(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length&&this._zooming){var i=this._map,n=i.mouseEventToContainerPoint(t.touches[0]),o=i.mouseEventToContainerPoint(t.touches[1]),s=n.distanceTo(o)/this._startDist;if(this._zoom=i.getScaleZoom(s,this._startZoom),!i.options.bounceAtZoomLimits&&(this._zoomi.getMaxZoom()&&s>1)&&(this._zoom=i._limitZoom(this._zoom)),"center"===i.options.touchZoom){if(this._center=this._startLatLng,1===s)return}else{var r=n._add(o)._divideBy(2)._subtract(this._centerPoint);if(1===s&&0===r.x&&0===r.y)return;this._center=i.unproject(i.project(this._pinchStartLatLng,this._zoom).subtract(r),this._zoom)}this._moved||(i._moveStart(!0),this._moved=!0),g(this._animRequest);var a=e(i._move,i,this._center,this._zoom,{pinch:!0,round:!1});this._animRequest=f(a,this,!0),$(t)}},_onTouchEnd:function(){return this._moved&&this._zooming?(this._zooming=!1,g(this._animRequest),G(document,"touchmove",this._onTouchMove),G(document,"touchend",this._onTouchEnd),void(this._map.options.zoomAnimation?this._map._animateZoom(this._center,this._map._limitZoom(this._zoom),!0,this._map.options.zoomSnap):this._map._resetView(this._center,this._map._limitZoom(this._zoom)))):void(this._zooming=!1)}});Se.addInitHook("addHandler","touchZoom",qn),Se.BoxZoom=Wn,Se.DoubleClickZoom=Hn,Se.Drag=Fn,Se.Keyboard=Un,Se.ScrollWheelZoom=Vn,Se.Tap=Gn,Se.TouchZoom=qn;var Kn=window.L;window.L=t,t.version="1.1.0",t.noConflict=li,t.Control=ke,t.control=Be,t.Browser=ae,t.Evented=wi,t.Mixin=Ue,t.Util=yi,t.Class=v,t.Handler=Fe,t.extend=i,t.bind=e,t.stamp=n,t.setOptions=l,t.DomEvent=Le,t.DomUtil=Ze,t.PosAnimation=Ee,t.Draggable=Ye,t.LineUtil=Xe,t.PolyUtil=Je,t.Point=x,t.point=w,t.Bounds=P,t.bounds=b,t.Transformation=Z,t.transformation=E,t.Projection=tn,t.LatLng=M,t.latLng=C,t.LatLngBounds=T,t.latLngBounds=z,t.CRS=Li,t.GeoJSON=yn,t.geoJSON=ii,t.geoJson=wn,t.Layer=sn,t.LayerGroup=rn,t.layerGroup=an,t.FeatureGroup=hn,t.featureGroup=un,t.ImageOverlay=Ln,t.imageOverlay=Pn,t.VideoOverlay=bn,t.videoOverlay=ei,t.DivOverlay=Tn,t.Popup=zn,t.popup=Mn,t.Tooltip=Cn,t.tooltip=Zn,t.Icon=ln,t.icon=Ht,t.DivIcon=En,t.divIcon=ni,t.Marker=dn,t.marker=Ft,t.TileLayer=kn,t.tileLayer=si,t.GridLayer=Sn,t.gridLayer=oi,t.SVG=Nn,t.svg=hi,t.Renderer=In,t.Canvas=An,t.canvas=ai,t.Path=pn,t.CircleMarker=mn,t.circleMarker=Ut,t.Circle=fn,t.circle=Vt,t.Polyline=gn,t.polyline=Gt,t.Polygon=vn,t.polygon=qt,t.Rectangle=jn,t.rectangle=ui,t.Map=Se,t.map=Ct}) \ 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 ac93508be615c5d062f3bfa51d06e61d0114c23d..7f5a96d3c93b0a2722969ced358fd1fe9dd3163e 100644 GIT binary patch delta 2044 zcmZ2_lWEmWrVY7s>kXAGXROfpH{bTqmPZmfpA`N)y3F$;^NnP-ob`^Cp(&py*6m&M zEb+rvztx>{*Ehe&=2w!+vndIx&AfY2P9%HMqkn-$Oc#&xtx1%YG|4(9{x0{~s(T$_ zwhmphmt?017w0??Tc4@=f?0g_()%6WS5_?)F4eW;>srFaw0h?Dn@oB2VXFmarkDtd zr0!po(rEj2rvYF86-S{Znjh|ja4_!-d$pYB>fh;&N1yUcI5|;Il~G%<&RRw;@W4xf z84g0~oR?popC8Kf^E2bJT=g4wdCNkKK6PK@TQ%d(%sqeBr9F%8`CEC5y^8t9M!Rm$ zoNxCI@B9AAigVd%sfd$ysw}n-ExhVII8{zuobjOZ(T5-UirqW+x_H&jI`{jfjlK4< z1IxEX{_Q+l@9e8`y4^NqF{}AL^Bd>&)K=V8luA;HGeBh+Sg+>A4~Dhp*pSYnWGA zdYIw$@tgW-XP&>fIs1N6PS^a)J&!HVxP7o)?;lWAEndHx&04~1akt;Ji|@9rmN4+F zyqm)MNpOjX_?#u1H@~Uf)sXkZ|M*AcefRb?axO{NR8Bo+RCHmIk4kFY92tl0r+!ry zMzL*dn;ObKH#On}v-rwh(+kfp%1ldqIPnAT6l?!U5``~Vr@pA^Vr~t(8ywLRYT zHa=Bd{`0c^Yc{&HIWY-+@n!fi|JKU4Nolo3#~hNJu6oX$w=DGDX6vV}N#fNf7M*tc z!1$JFgUZ=0hdgSvZyPckx>5Nh!y+ceJ4I(-%HyteFSsjDZ!q7(|3D_tDziGYD$n+g zgzbW_k3v&hnN9R^-YWSg%AHK(6>bTe>Y{a}I44j4Qnr}U<)FN$;@z9FE-m`#Q+Xkb zfAX9K(oEsGlXos~RAc#TwEpwtn!cbsarFys3Ge<~(@@L0xAmi-{=a~EixnR;op{Nu zxp=a|LJQ9QB37#3dWF6mo1C~%gfV$?*+PZj)e*1VHkB8Ip3A>|W%I@t!ngDP%-D9< zrh0PHt21X^e?^ra=yyA28mebwzJzgYSpGM&L%+_sdc6=`ks2POe{M5^KnxxBT>~wrw{ za@grIvDtCw=OfJPgjd{Ul2p65HZAh~>BUOSw-#TREU?&|$xLms=i*ZKS4TJgwOn># z^3lcWjFFSyE;eHPFX z%>K)u#!+%Kr1MvWZ_|ydp4WD5SiQBAclYVYsd0aKP4gC}6o?xa6g>k|6G4-{N!CL z{ROi1e(&0~OX`4;SZOfhh7&Uq4QA+X__JqD#N>rJO0^?XXq;lJ3Xy>XVA?b4QW z4+>PT|9s@Vc)yOJO3xI*-%eg;%nP0#I%sz@Zsv!$=d$|dO8yrNdQMD!yGq6??|flR zMb2icEOYfmVTpID^onOJx*yJH#A5Jkw?%9l=uHRGkL;l5ig5H zocZTxcmLecwUI||-^Yjd4p+Q?7-$pfw$DM+t?*djKAxV=rq3TPyb6~UwGL(apt0|0 z-m%o27bOWkp1aJCw;ociRB=+-y?4|4$?sO{G47u%yCzoqUBmy$(&; delta 2043 zcmZ2=lWFNqrVY7s>wn7IuidgkBK(uWpGVEyGcshh8K%ftXRHWK`8=_1@0w?cAHMpn z?wq^6`9(JWImtYml1oLIvB%|dvV!jZ3p84H;V9plL}^KrEH~bFN1tZh>s)fR(y7zu|RdF$`p1J)dlV0Fz!I>%bCW0cV`xm7& zYJ3$mIM*3sE)=4%;d%&1^0u&7%X?1!o!)r#0?&l`6YnWAGAe3W%g6=hycGChJ4uF9 z`{nuhp-em9G5*U@zj2qhEW~J2+eN;t$#-Vv{9gC$cC^i(%3JK0m@L-YdAsEJ-8;PU z`zI^TWv8Wf9J5npv3;oQ#lfO-;$nT?gU+O9KlByLcJ6gqR5R<`@0T|A+Q$w|+P3po z=h-Z0-z5jyZJ*3weZ1HF#(6!p6(lByy;-I?P%iADSA7M)pk@2-FB*yn$uzkGge zeed`7dQr{C2Q_xTILLJ<_UIpLhwk(PXA1AU?>=$K;;K2=@* z^RoSGHoCNZVwm*Om*L0!TPxotrPY4g?I7fM)pPE=Wuf;rTR(M8%C9=nd)n>8+BZxa zRL*WWw4g@&wjslz8zdWF8s$#`C$U4C$daZ!Us2@;-a8*N4b`(TU&6RHEdQI?p`;M($<8u6Y znC+#T*LQqgv3LA@WQoq*)2cF(%w&Z!o zJk#b1-+ko~tF<@}IaJzD{=G<&QDd^`VsoZ#(v$rbm$J_~vhlCwGL6Zn7OOMrPyV#n z$RMDrK=}FRnNv2-z479#Go+t!}kz3%I6S1aYI zhAi5fcI|clblsBYbJf`ES7_TyU@iI52v(=MdFOy?>b8<5Ga!roy`L%s2o3B+(wpnh$)F(Z; zYwPBOnE4NigFFj=4DJWr+&dE`2r11FG~NPSSpTIN{`C!F!8L_L?TieKeeL?M3*xk2_ZF=~^Jpc+>t5OHzfx+%+=q z`q_RT{=36oqOM+~Urs~(x&Bt}$@^FO3xw(Y-nDC&)Bz*0(qP67C-NuDtum-TR-=5s zbn*Ll8XUsAG(=|IeYTG?)g}AoUBk8cT`Qj&6i*PJ{(?vF97DBrcdL^HpG^z5Ozi5G zL*G+N#EacdPkooNqQ`_$O8-HGr+Q3VzueAsFJ1(!UGh?!*S%|AlHX_JAFEGYSnGL@ zL8;4n)9FV&pAvKUFScoKoMkq5QOmgp1@+f|I(aV6)-hD!=@R_C$lZ*2!P7$r?QX`+ z{1Eq?L*Kl~=Ym0xLZXe%fqV7MpQUbj{mD^pXPzaY7P=~|sKO-iPovzq!kUVl%~o0F z>P#Vt9aVb8GZuA+Ga9iN?Aj*D@z~AikMiT+vubj4TQ{^$(LLJm^W)pM4}@jvOERxt zJo9<7&uWeOIcH`aU<$mIs#e>&QGS!cgooExAJOW4bHGs{C-y;kf6S>G**9Cf-m=7N zFBbbzBh=HqM{eK8hxZOwynh&I6Z&nBgQi>IF~+?-J)KRT zKU{bfE-Pvs%Je~F-_g8dsW~r75`K8>GC$sWNV!sFk>c*Xo1!OwUaiNtYO>OrSf+XP hlN;9vi_Jc;A@UG|E=NtoUG@LsM^FBc5lLWT000N3^u7Q9 diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html index 99d4b1db86e..20d85cfdee9 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.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-shopping-list.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html.gz index f80112f596de006935b9393f102991d2ac6264aa..6c71d75c39096ba7237d6622b4046bb8c125c169 100644 GIT binary patch delta 5091 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 delta 5088 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 V?8xhn%(wj$KVx \ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-zwave.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-zwave.html.gz index 271ecd66614574e05e16afc3d92badd497f1a482..9c93970e3362608d6013993438de8f079b7cd37f 100644 GIT binary patch delta 8566 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 delta 8561 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 g)9dTafF(*OEb4=uD!7Gq!l02H;~YybcN literal 2487 zcmb2|=3oE;Cg!CP*~Pbai2l{)TK-x!yNm6|vQXbN^Shbb@7_)MG^562ucW|^DKi3= zcsZ5D9RI(UeTjs<#U`A3f~{y`P_~n`|8CNmvc3@nren^y^)Nz5e0AQwxqF5G?(%-i%N)+B`yo5LFa24J zZd(6y!>6xqtHxg1TbvA{T+0FX0aZ#yzuw8!M68n#C_K`KK-FAgR$m~MUgZ$s0BZGZgj z%QOFaELvKYGWT`$@w3vU)j#{q_3JzbdF3;8$7$}G!FJOP-v>6xg?)$+O;i(_dURsYByp{-E|qY{zz6TQ%-f_lYomP7 ztYs>~6S-E-;Mt_Xe@LNQGr8w^(PFie#pfPRnJxQ7$-gMFL#9fURps*XDvq7;cX#?(fyO-)ND9o=&A$W)D>lZ$?)BrpB_Qg9~c7Wj=eROg!;;Nk@Xi#KL#R)4HYvPxebbsmUbO#Q19fabehUJJo(f$%p^;LsaMFiqJW4Y}4<`Qf4E4}{ zEVGY4=-p|H=KNs6bSGA?h7earPq{pk1D%sjFPLB$m%O@Cq}bEvgVHHak&6osGK8Gs zzNs@!;z?@gtJ{TMigPBqyS{Ml;BjP|*R3NG$#=f!{_iV}jx!9-ESVTkHzn{vyHSIs zPs^H)P%)K$ku4@+3q4Ziotkp;#`(nxevc+dG&*I59C6|)YHn$opi;Nl>4QeoVh5oJ zp(jTK_f!{|bM%TnUU)uIhugl@b|dFTjqj0XcFY%hX=brWd7I)H7zCc(QhSQ zmO%ZAWYeB^dbiZ_ONu}4s_&`K(R!L0JHv%>lGjY7S4jpFix0@OPEc-nWZB)E-}!6l zoU>n}!kEmTX(}CfUn|bW$~=SP@qzCXy$J@Sj^qOEbR(vnQ&)n*sMbZfgRb#5}(if zZ?eyiJkKLoIc=kYKcgUz5a*6V8xG6->?)q;qW-kvNBSW<7q_!hJr+zovrXf`?=(f)Y#aawG)5(>SSb< znm_ivDjCoIcw=c^d5CD7_huo{Rr-nN`P26JnXULT?dguEYutJkU9D7&^0=~M;(jiX zs4LrEws+qTulo4$(J4`{zoMe|uROm!Kif5a8NY9j=AUK1I#;gT{66k~Q*ubo-}c37i+WL=-Ce%<(dp9)-&$VX6!_)c*Yo;jDTmX}uU%RCrnf*Q{N2t4 zZ{i#u{o^Jm-*jzIAwWv%liE@qm~uxpW>R;U%SHgOXl0R zf^N3XX3O|u|FV}o{qpy}XYBl0o9?ZUI%e=T(C3V+`FleNr~i-r-bCy9N!-1i=Dc>D z`{VG8+wVR3c?>SRTxobgwBm#I_PP&qZmajLlH8U2A$ga7!tQ(9Ic4gOnZKxCQQlMj z^y=QnK2?<`RR1PE6L(%EHA5*+&{}lW%XO(w?sf$2UtJn`^Dmzjzvb#}+fTm#lKJWb zPr1=E^FXez-}rO2^K7?>asL*ab#Lp6uq!j4Y-C^XVlhJ=8;@F3l?6LP{N?@O$G#uh z%bdaWTi5k!Y?Q2y{NoZs?d;cer>{KB36|ejJmG##*_S=JdB0@72H!Sw$X%NlV)Cp& z>D=0j3O!dm5-gr)WnaXFZymLk0KaCV#y}Uswf2Yyzi?$QrKRm00`R%%YXXJLRTAvhIXS#FMuU&Q-b$c>zoxieZ{jXgDrI8Ym&szF5%KrUPH%Y0s zejhz4_noo&_rGtp&pzvyclhcvuVfCpuW}2&?-wr8Xy|`>eue(U_SX+;Ze7YVQt2#h zs<2)jxIV~s3A3$uRf+O0!P>}gdoQneEacpv<9~itE?zPmN5lo_c-Bny*u5 z?R1U4ziVduPOs`6w#DY_A7lp zQs37+wE1<;aCKSHJFD8SXZ|vF7WJOxb=tpkV_$6bH`&?I{tlunva>t(=iEBcX<=XP z@Ji}#hl6?27e(nAZvsq;uFh23e@|fFw_ldGXC@py#v`2dzWVC9Z6|E&l3y?1{AQnV b!@YgR^GcZaz1!RH>R Date: Tue, 25 Jul 2017 00:42:59 -0700 Subject: [PATCH 092/118] Tweak conversation/intent/shopping list (#8636) --- homeassistant/components/conversation.py | 8 +++++++- homeassistant/components/shopping_list.py | 13 +++++++++---- homeassistant/helpers/intent.py | 2 +- tests/components/test_shopping_list.py | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/conversation.py b/homeassistant/components/conversation.py index b682b318c7b..303e83e7e0e 100644 --- a/homeassistant/components/conversation.py +++ b/homeassistant/components/conversation.py @@ -151,7 +151,7 @@ def _process(hass, text): if not entity_ids: _LOGGER.error( "Could not find entity id %s from text %s", name, text) - return + return None if command == 'on': yield from hass.services.async_call( @@ -169,6 +169,8 @@ def _process(hass, text): _LOGGER.error('Got unsupported command %s from text %s', command, text) + return None + class ConversationProcessView(http.HomeAssistantView): """View to retrieve shopping list content.""" @@ -194,4 +196,8 @@ class ConversationProcessView(http.HomeAssistantView): intent_result = yield from _process(hass, text) + if intent_result is None: + intent_result = intent.IntentResponse() + intent_result.async_set_speech("Sorry, I didn't understand that") + return self.json(intent_result) diff --git a/homeassistant/components/shopping_list.py b/homeassistant/components/shopping_list.py index 7247579fa39..ac59c15572a 100644 --- a/homeassistant/components/shopping_list.py +++ b/homeassistant/components/shopping_list.py @@ -70,11 +70,16 @@ class ListTopItemsIntent(intent.IntentHandler): @asyncio.coroutine def async_handle(self, intent_obj): """Handle the intent.""" + items = intent_obj.hass.data[DOMAIN][-5:] response = intent_obj.create_response() - response.async_set_speech( - "These are the top 5 items in your shopping list: {}".format( - ', '.join(reversed(intent_obj.hass.data[DOMAIN][-5:])))) - intent_obj.hass.bus.async_fire(EVENT) + + if len(items) == 0: + response.async_set_speech( + "There are no items on your shopping list") + else: + response.async_set_speech( + "These are the top {} items on your shopping list: {}".format( + min(len(items), 5), ', '.join(reversed(items)))) return response diff --git a/homeassistant/helpers/intent.py b/homeassistant/helpers/intent.py index 459d89a83ce..8843bf53df9 100644 --- a/homeassistant/helpers/intent.py +++ b/homeassistant/helpers/intent.py @@ -134,7 +134,7 @@ class Intent: class IntentResponse: """Response to an intent.""" - def __init__(self, intent): + def __init__(self, intent=None): """Initialize an IntentResponse.""" self.intent = intent self.speech = {} diff --git a/tests/components/test_shopping_list.py b/tests/components/test_shopping_list.py index 867e695e2d5..c25ce593c54 100644 --- a/tests/components/test_shopping_list.py +++ b/tests/components/test_shopping_list.py @@ -38,7 +38,7 @@ def test_recent_items_intent(hass): ) assert response.speech['plain']['speech'] == \ - "These are the top 5 items in your shopping list: soda, wine, beer" + "These are the top 3 items on your shopping list: soda, wine, beer" @asyncio.coroutine From cd2703e1216dc93363153fba4971861b618a5196 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 25 Jul 2017 23:35:05 -0700 Subject: [PATCH 093/118] Update dependencies cast + discovery (#8646) --- homeassistant/components/discovery.py | 2 +- homeassistant/components/media_player/cast.py | 2 +- requirements_all.txt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/discovery.py b/homeassistant/components/discovery.py index 3dfe4b9731c..af4604cb7d7 100644 --- a/homeassistant/components/discovery.py +++ b/homeassistant/components/discovery.py @@ -21,7 +21,7 @@ from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.helpers.discovery import async_load_platform, async_discover import homeassistant.util.dt as dt_util -REQUIREMENTS = ['netdisco==1.0.1'] +REQUIREMENTS = ['netdisco==1.1.0'] DOMAIN = 'discovery' diff --git a/homeassistant/components/media_player/cast.py b/homeassistant/components/media_player/cast.py index 51acf68d819..c416157169e 100644 --- a/homeassistant/components/media_player/cast.py +++ b/homeassistant/components/media_player/cast.py @@ -20,7 +20,7 @@ from homeassistant.const import ( import homeassistant.helpers.config_validation as cv import homeassistant.util.dt as dt_util -REQUIREMENTS = ['pychromecast==0.8.1'] +REQUIREMENTS = ['pychromecast==0.8.2'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index aa99cd03701..ce220e17399 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -410,7 +410,7 @@ myusps==1.1.2 nad_receiver==0.0.6 # homeassistant.components.discovery -netdisco==1.0.1 +netdisco==1.1.0 # homeassistant.components.sensor.neurio_energy neurio==0.3.1 @@ -541,7 +541,7 @@ pybbox==0.0.5-alpha # pybluez==0.22 # homeassistant.components.media_player.cast -pychromecast==0.8.1 +pychromecast==0.8.2 # homeassistant.components.media_player.cmus pycmus==0.1.0 From e83816c05523412b3f4efdc941d90288441b571a Mon Sep 17 00:00:00 2001 From: Sean Gollschewsky Date: Wed, 26 Jul 2017 08:04:40 +0100 Subject: [PATCH 094/118] Add component Light TPLink (#8643) * Add new component for TPLink light bulbs. * Update with result of gen_requirements_all. * Add new component light.tplink. --- .coveragerc | 1 + homeassistant/components/light/tplink.py | 116 +++++++++++++++++++++++ requirements_all.txt | 1 + 3 files changed, 118 insertions(+) create mode 100644 homeassistant/components/light/tplink.py diff --git a/.coveragerc b/.coveragerc index dc2f39b9977..c9bd40dfc65 100644 --- a/.coveragerc +++ b/.coveragerc @@ -306,6 +306,7 @@ omit = homeassistant/components/light/piglow.py homeassistant/components/light/sensehat.py homeassistant/components/light/tikteck.py + homeassistant/components/light/tplink.py homeassistant/components/light/tradfri.py homeassistant/components/light/x10.py homeassistant/components/light/yeelight.py diff --git a/homeassistant/components/light/tplink.py b/homeassistant/components/light/tplink.py new file mode 100644 index 00000000000..333661870d1 --- /dev/null +++ b/homeassistant/components/light/tplink.py @@ -0,0 +1,116 @@ +""" +Support for TPLink lights. + +For more details about this component, please refer to the documentation at +https://home-assistant.io/components/light.tplink/ +""" +import logging +from homeassistant.const import (CONF_HOST, CONF_NAME) +from homeassistant.components.light import ( + Light, ATTR_BRIGHTNESS, ATTR_COLOR_TEMP, ATTR_KELVIN, + SUPPORT_BRIGHTNESS, SUPPORT_COLOR_TEMP) +from homeassistant.util.color import \ + color_temperature_mired_to_kelvin as mired_to_kelvin +from homeassistant.util.color import \ + color_temperature_kelvin_to_mired as kelvin_to_mired + +REQUIREMENTS = ['pyHS100==0.2.4.2'] + +_LOGGER = logging.getLogger(__name__) + +SUPPORT_TPLINK = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Initialise pyLB100 SmartBulb.""" + from pyHS100 import SmartBulb + host = config.get(CONF_HOST) + name = config.get(CONF_NAME) + add_devices([TPLinkSmartBulb(SmartBulb(host), name)], True) + + +def brightness_to_percentage(byt): + """Convert brightness from absolute 0..255 to percentage.""" + return (byt*100.0)/255.0 + + +def brightness_from_percentage(percent): + """Convert percentage to absolute value 0..255.""" + return (percent*255.0)/100.0 + + +class TPLinkSmartBulb(Light): + """Representation of a TPLink Smart Bulb.""" + + def __init__(self, smartbulb, name): + """Initialize the bulb.""" + self.smartbulb = smartbulb + + # Use the name set on the device if not set + if name is None: + self._name = self.smartbulb.alias + else: + self._name = name + + self._state = None + _LOGGER.debug("Setting up TP-Link Smart Bulb") + + @property + def name(self): + """Return the name of the Smart Bulb, if any.""" + return self._name + + def turn_on(self, **kwargs): + """Turn the light on.""" + if ATTR_COLOR_TEMP in kwargs: + self.smartbulb.color_temp = \ + mired_to_kelvin(kwargs[ATTR_COLOR_TEMP]) + if ATTR_KELVIN in kwargs: + self.smartbulb.color_temp = kwargs[ATTR_KELVIN] + if ATTR_BRIGHTNESS in kwargs: + brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255) + self.smartbulb.brightness = brightness_to_percentage(brightness) + + self.smartbulb.state = self.smartbulb.BULB_STATE_ON + + def turn_off(self): + """Turn the light off.""" + self.smartbulb.state = self.smartbulb.BULB_STATE_OFF + + @property + def color_temp(self): + """Return the color temperature of this light in mireds for HA.""" + if self.smartbulb.is_color: + if (self.smartbulb.color_temp is not None and + self.smartbulb.color_temp != 0): + return kelvin_to_mired(self.smartbulb.color_temp) + else: + return None + else: + return None + + @property + def brightness(self): + """Return the brightness of this light between 0..255.""" + return brightness_from_percentage(self.smartbulb.brightness) + + @property + def is_on(self): + """True if device is on.""" + return self.smartbulb.state == \ + self.smartbulb.BULB_STATE_ON + + def update(self): + """Update the TP-Link Bulb's state.""" + from pyHS100 import SmartPlugException + try: + self._state = self.smartbulb.state == \ + self.smartbulb.BULB_STATE_ON + + except (SmartPlugException, OSError) as ex: + _LOGGER.warning('Could not read state for %s: %s', self.name, ex) + + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_TPLINK diff --git a/requirements_all.txt b/requirements_all.txt index ce220e17399..d8c3bfa8abe 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -509,6 +509,7 @@ py-cpuinfo==3.3.0 # homeassistant.components.hdmi_cec pyCEC==0.4.13 +# homeassistant.components.light.tplink # homeassistant.components.switch.tplink pyHS100==0.2.4.2 From 7c120748ce9605d0fb3d8cad0ea40032e116c205 Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Wed, 26 Jul 2017 05:05:48 -0400 Subject: [PATCH 095/118] Fixes Fitbit sensor to report battery level with the expected device (#8647) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an optional extended description… --- homeassistant/components/sensor/fitbit.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/fitbit.py b/homeassistant/components/sensor/fitbit.py index 0c10d2159ea..c0256e3a88b 100644 --- a/homeassistant/components/sensor/fitbit.py +++ b/homeassistant/components/sensor/fitbit.py @@ -433,9 +433,8 @@ class FitbitSensor(Entity): def update(self): """Get the latest data from the Fitbit API and update the states.""" - if self.resource_type == 'devices/battery': - response = self.client.get_devices() - self._state = response[0].get('battery') + if self.resource_type == 'devices/battery' and self.extra: + self._state = self.extra.get('battery') else: container = self.resource_type.replace("/", "-") response = self.client.time_series(self.resource_type, period='7d') From 81a27e726ce9df9d2eb0c88441db6c8a31161d93 Mon Sep 17 00:00:00 2001 From: Anders Melchiorsen Date: Wed, 26 Jul 2017 12:33:00 +0200 Subject: [PATCH 096/118] Upgrade aiolifx (#8648) This release includes a fix for multizone lights with zone counts that are not a multiple of eight. --- homeassistant/components/light/lifx.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/light/lifx.py b/homeassistant/components/light/lifx.py index a6c5f855875..908a9d24e04 100644 --- a/homeassistant/components/light/lifx.py +++ b/homeassistant/components/light/lifx.py @@ -33,7 +33,7 @@ import homeassistant.util.color as color_util _LOGGER = logging.getLogger(__name__) -REQUIREMENTS = ['aiolifx==0.5.2', 'aiolifx_effects==0.1.1'] +REQUIREMENTS = ['aiolifx==0.5.4', 'aiolifx_effects==0.1.1'] UDP_BROADCAST_PORT = 56700 diff --git a/requirements_all.txt b/requirements_all.txt index d8c3bfa8abe..9820d0888cd 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -49,7 +49,7 @@ aiodns==1.1.1 aiohttp_cors==0.5.3 # homeassistant.components.light.lifx -aiolifx==0.5.2 +aiolifx==0.5.4 # homeassistant.components.light.lifx aiolifx_effects==0.1.1 From fff269e790b1e741e43a360ec6502d166b6b73b2 Mon Sep 17 00:00:00 2001 From: Thomas Delaet Date: Wed, 26 Jul 2017 14:03:29 +0200 Subject: [PATCH 097/118] Velbus (#8076) * add Velbus changes * update library version * fix python-velbus version * bug fix and update python-velbus * change config handling * update velbus components/platforms * add support for Velbus switches * fix bugs * typo * add velbus fan * update velbus library * bug fix in logic of fan handling of speed settings * add Velbus changes change config handling update velbus components/platforms add support for Velbus switches add velbus fan * remove duplicate entry * fix documentation links * fix linting error * regen requirements_all.txt * add support for Velbus cover * bugfix in cover component * bugfix in cover component * remove unused imports * Travis fixes * fix style * fix style * Update velbus.py * Update velbus.py * Update velbus.py * Update requirements_all.txt * Update velbus.py * Update velbus.py * Update velbus.py * Update velbus.py * fix style * Update velbus.py * Update velbus.py * Update velbus.py * Update velbus.py * Update velbus.py * Update velbus.py --- .coveragerc | 3 + .../components/binary_sensor/velbus.py | 96 +++++++++ homeassistant/components/cover/velbus.py | 160 +++++++++++++++ homeassistant/components/fan/velbus.py | 187 ++++++++++++++++++ homeassistant/components/light/velbus.py | 104 ++++++++++ homeassistant/components/switch/velbus.py | 111 +++++++++++ homeassistant/components/velbus.py | 43 ++++ requirements_all.txt | 3 + 8 files changed, 707 insertions(+) create mode 100644 homeassistant/components/binary_sensor/velbus.py create mode 100644 homeassistant/components/cover/velbus.py create mode 100644 homeassistant/components/fan/velbus.py create mode 100644 homeassistant/components/light/velbus.py create mode 100644 homeassistant/components/switch/velbus.py create mode 100644 homeassistant/components/velbus.py diff --git a/.coveragerc b/.coveragerc index c9bd40dfc65..c4051af5136 100644 --- a/.coveragerc +++ b/.coveragerc @@ -172,6 +172,9 @@ omit = homeassistant/components/twilio.py homeassistant/components/notify/twilio_sms.py homeassistant/components/notify/twilio_call.py + + homeassistant/components/velbus.py + homeassistant/components/*/velbus.py homeassistant/components/velux.py homeassistant/components/*/velux.py diff --git a/homeassistant/components/binary_sensor/velbus.py b/homeassistant/components/binary_sensor/velbus.py new file mode 100644 index 00000000000..214edcf9463 --- /dev/null +++ b/homeassistant/components/binary_sensor/velbus.py @@ -0,0 +1,96 @@ +""" +Support for Velbus Binary Sensors. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/binary_sensor.velbus/ +""" +import asyncio +import logging + + +import voluptuous as vol + +from homeassistant.const import CONF_NAME, CONF_DEVICES +from homeassistant.components.binary_sensor import BinarySensorDevice +from homeassistant.components.binary_sensor import PLATFORM_SCHEMA +from homeassistant.components.velbus import DOMAIN +import homeassistant.helpers.config_validation as cv + + +DEPENDENCIES = ['velbus'] + +_LOGGER = logging.getLogger(__name__) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DEVICES): vol.All(cv.ensure_list, [ + { + vol.Required('module'): cv.positive_int, + vol.Required('channel'): cv.positive_int, + vol.Required(CONF_NAME): cv.string, + vol.Optional('is_pushbutton'): cv.boolean + } + ]) +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up Velbus binary sensors.""" + velbus = hass.data[DOMAIN] + + add_devices(VelbusBinarySensor(sensor, velbus) + for sensor in config[CONF_DEVICES]) + + +class VelbusBinarySensor(BinarySensorDevice): + """Representation of a Velbus Binary Sensor.""" + + def __init__(self, binary_sensor, velbus): + """Initialize a Velbus light.""" + self._velbus = velbus + self._name = binary_sensor[CONF_NAME] + self._module = binary_sensor['module'] + self._channel = binary_sensor['channel'] + self._is_pushbutton = 'is_pushbutton' in binary_sensor \ + and binary_sensor['is_pushbutton'] + self._state = False + + @asyncio.coroutine + def async_added_to_hass(self): + """Add listener for Velbus messages on bus.""" + yield from self.hass.async_add_job( + self._velbus.subscribe, self._on_message) + + def _on_message(self, message): + import velbus + if isinstance(message, velbus.PushButtonStatusMessage): + if message.address == self._module and \ + self._channel in message.get_channels(): + if self._is_pushbutton: + if self._channel in message.closed: + self._toggle() + else: + pass + else: + self._toggle() + + def _toggle(self): + if self._state is True: + self._state = False + else: + self._state = True + self.schedule_update_ha_state() + + @property + def should_poll(self): + """No polling needed.""" + return False + + @property + def name(self): + """Return the display name of this sensor.""" + return self._name + + @property + def is_on(self): + """Return true if the sensor is on.""" + return self._state diff --git a/homeassistant/components/cover/velbus.py b/homeassistant/components/cover/velbus.py new file mode 100644 index 00000000000..ab5d6e8ef79 --- /dev/null +++ b/homeassistant/components/cover/velbus.py @@ -0,0 +1,160 @@ +""" +Support for Velbus covers. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/cover.velbus/ +""" +import logging +import asyncio +import time + +import voluptuous as vol + +from homeassistant.components.cover import ( + CoverDevice, PLATFORM_SCHEMA, SUPPORT_OPEN, SUPPORT_CLOSE, + SUPPORT_STOP) +from homeassistant.components.velbus import DOMAIN +from homeassistant.const import (CONF_COVERS, CONF_NAME) +import homeassistant.helpers.config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +COVER_SCHEMA = vol.Schema({ + vol.Required('module'): cv.positive_int, + vol.Required('open_channel'): cv.positive_int, + vol.Required('close_channel'): cv.positive_int, + vol.Required(CONF_NAME): cv.string +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_COVERS): vol.Schema({cv.slug: COVER_SCHEMA}), +}) + +DEPENDENCIES = ['velbus'] + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up cover controlled by Velbus.""" + devices = config.get(CONF_COVERS, {}) + covers = [] + + velbus = hass.data[DOMAIN] + for device_name, device_config in devices.items(): + covers.append( + VelbusCover( + velbus, + device_config.get(CONF_NAME, device_name), + device_config.get('module'), + device_config.get('open_channel'), + device_config.get('close_channel') + ) + ) + + if not covers: + _LOGGER.error("No covers added") + return False + + add_devices(covers) + + +class VelbusCover(CoverDevice): + """Representation a Velbus cover.""" + + def __init__(self, velbus, name, module, open_channel, close_channel): + """Initialize the cover.""" + self._velbus = velbus + self._name = name + self._close_channel_state = None + self._open_channel_state = None + self._module = module + self._open_channel = open_channel + self._close_channel = close_channel + + @asyncio.coroutine + def async_added_to_hass(self): + """Add listener for Velbus messages on bus.""" + def _init_velbus(): + """Initialize Velbus on startup.""" + self._velbus.subscribe(self._on_message) + self.get_status() + + yield from self.hass.async_add_job(_init_velbus) + + def _on_message(self, message): + import velbus + if isinstance(message, velbus.RelayStatusMessage): + if message.address == self._module: + if message.channel == self._close_channel: + self._close_channel_state = message.is_on() + self.schedule_update_ha_state() + if message.channel == self._open_channel: + self._open_channel_state = message.is_on() + self.schedule_update_ha_state() + + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP + + @property + def should_poll(self): + """Disable polling.""" + return False + + @property + def name(self): + """Return the name of the cover.""" + return self._name + + @property + def is_closed(self): + """Return if the cover is closed.""" + return self._close_channel_state + + @property + def current_cover_position(self): + """Return current position of cover. + + None is unknown. + """ + return None + + def _relay_off(self, channel): + import velbus + message = velbus.SwitchRelayOffMessage() + message.set_defaults(self._module) + message.relay_channels = [channel] + self._velbus.send(message) + + def _relay_on(self, channel): + import velbus + message = velbus.SwitchRelayOnMessage() + message.set_defaults(self._module) + message.relay_channels = [channel] + self._velbus.send(message) + + def open_cover(self, **kwargs): + """Open the cover.""" + self._relay_off(self._close_channel) + time.sleep(0.3) + self._relay_on(self._open_channel) + + def close_cover(self, **kwargs): + """Close the cover.""" + self._relay_off(self._open_channel) + time.sleep(0.3) + self._relay_on(self._close_channel) + + def stop_cover(self, **kwargs): + """Stop the cover.""" + self._relay_off(self._open_channel) + time.sleep(0.3) + self._relay_off(self._close_channel) + + def get_status(self): + """Retrieve current status.""" + import velbus + message = velbus.ModuleStatusRequestMessage() + message.set_defaults(self._module) + message.channels = [self._open_channel, self._close_channel] + self._velbus.send(message) diff --git a/homeassistant/components/fan/velbus.py b/homeassistant/components/fan/velbus.py new file mode 100644 index 00000000000..c0d125aa5ab --- /dev/null +++ b/homeassistant/components/fan/velbus.py @@ -0,0 +1,187 @@ +""" +Support for Velbus platform. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/fan.velbus/ +""" +import asyncio +import logging +import voluptuous as vol + +from homeassistant.components.fan import ( + SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH, FanEntity, SUPPORT_SET_SPEED, + PLATFORM_SCHEMA) +from homeassistant.components.velbus import DOMAIN +from homeassistant.const import CONF_NAME, CONF_DEVICES, STATE_OFF +import homeassistant.helpers.config_validation as cv + +DEPENDENCIES = ['velbus'] + +_LOGGER = logging.getLogger(__name__) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DEVICES): vol.All(cv.ensure_list, [ + { + vol.Required('module'): cv.positive_int, + vol.Required('channel_low'): cv.positive_int, + vol.Required('channel_medium'): cv.positive_int, + vol.Required('channel_high'): cv.positive_int, + vol.Required(CONF_NAME): cv.string, + } + ]) +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up Fans.""" + velbus = hass.data[DOMAIN] + add_devices(VelbusFan(fan, velbus) for fan in config[CONF_DEVICES]) + + +class VelbusFan(FanEntity): + """Representation of a Velbus Fan.""" + + def __init__(self, fan, velbus): + """Initialize a Velbus light.""" + self._velbus = velbus + self._name = fan[CONF_NAME] + self._module = fan['module'] + self._channel_low = fan['channel_low'] + self._channel_medium = fan['channel_medium'] + self._channel_high = fan['channel_high'] + self._channels = [self._channel_low, self._channel_medium, + self._channel_high] + self._channels_state = [False, False, False] + self._speed = STATE_OFF + + @asyncio.coroutine + def async_added_to_hass(self): + """Add listener for Velbus messages on bus.""" + def _init_velbus(): + """Initialize Velbus on startup.""" + self._velbus.subscribe(self._on_message) + self.get_status() + + yield from self.hass.async_add_job(_init_velbus) + + def _on_message(self, message): + import velbus + if isinstance(message, velbus.RelayStatusMessage) and \ + message.address == self._module and \ + message.channel in self._channels: + if message.channel == self._channel_low: + self._channels_state[0] = message.is_on() + elif message.channel == self._channel_medium: + self._channels_state[1] = message.is_on() + elif message.channel == self._channel_high: + self._channels_state[2] = message.is_on() + self._calculate_speed() + self.schedule_update_ha_state() + + def _calculate_speed(self): + if self._is_off(): + self._speed = STATE_OFF + elif self._is_low(): + self._speed = SPEED_LOW + elif self._is_medium(): + self._speed = SPEED_MEDIUM + elif self._is_high(): + self._speed = SPEED_HIGH + + def _is_off(self): + return self._channels_state[0] is False and \ + self._channels_state[1] is False and \ + self._channels_state[2] is False + + def _is_low(self): + return self._channels_state[0] is True and \ + self._channels_state[1] is False and \ + self._channels_state[2] is False + + def _is_medium(self): + return self._channels_state[0] is True and \ + self._channels_state[1] is True and \ + self._channels_state[2] is False + + def _is_high(self): + return self._channels_state[0] is True and \ + self._channels_state[1] is False and \ + self._channels_state[2] is True + + @property + def name(self): + """Return the display name of this light.""" + return self._name + + @property + def should_poll(self): + """Disable polling.""" + return False + + @property + def speed(self): + """Return the current speed.""" + return self._speed + + @property + def speed_list(self): + """Get the list of available speeds.""" + return [STATE_OFF, SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH] + + def turn_on(self, speed, **kwargs): + """Turn on the entity.""" + if speed is None: + speed = SPEED_MEDIUM + self.set_speed(speed) + + def turn_off(self): + """Turn off the entity.""" + self.set_speed(STATE_OFF) + + def set_speed(self, speed): + """Set the speed of the fan.""" + channels_off = [] + channels_on = [] + if speed == STATE_OFF: + channels_off = self._channels + elif speed == SPEED_LOW: + channels_off = [self._channel_medium, self._channel_high] + channels_on = [self._channel_low] + elif speed == SPEED_MEDIUM: + channels_off = [self._channel_high] + channels_on = [self._channel_low, self._channel_medium] + elif speed == SPEED_HIGH: + channels_off = [self._channel_medium] + channels_on = [self._channel_low, self._channel_high] + for channel in channels_off: + self._relay_off(channel) + for channel in channels_on: + self._relay_on(channel) + self.schedule_update_ha_state() + + def _relay_on(self, channel): + import velbus + message = velbus.SwitchRelayOnMessage() + message.set_defaults(self._module) + message.relay_channels = [channel] + self._velbus.send(message) + + def _relay_off(self, channel): + import velbus + message = velbus.SwitchRelayOffMessage() + message.set_defaults(self._module) + message.relay_channels = [channel] + self._velbus.send(message) + + def get_status(self): + """Retrieve current status.""" + import velbus + message = velbus.ModuleStatusRequestMessage() + message.set_defaults(self._module) + message.channels = self._channels + self._velbus.send(message) + + @property + def supported_features(self): + """Flag supported features.""" + return SUPPORT_SET_SPEED diff --git a/homeassistant/components/light/velbus.py b/homeassistant/components/light/velbus.py new file mode 100644 index 00000000000..8a02b36b75f --- /dev/null +++ b/homeassistant/components/light/velbus.py @@ -0,0 +1,104 @@ +""" +Support for Velbus lights. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/light.velbus/ +""" +import asyncio +import logging + +import voluptuous as vol + +from homeassistant.const import CONF_NAME, CONF_DEVICES +from homeassistant.components.light import Light, PLATFORM_SCHEMA +from homeassistant.components.velbus import DOMAIN +import homeassistant.helpers.config_validation as cv + +DEPENDENCIES = ['velbus'] + +_LOGGER = logging.getLogger(__name__) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DEVICES): vol.All(cv.ensure_list, [ + { + vol.Required('module'): cv.positive_int, + vol.Required('channel'): cv.positive_int, + vol.Required(CONF_NAME): cv.string + } + ]) +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up Lights.""" + velbus = hass.data[DOMAIN] + add_devices(VelbusLight(light, velbus) for light in config[CONF_DEVICES]) + + +class VelbusLight(Light): + """Representation of a Velbus Light.""" + + def __init__(self, light, velbus): + """Initialize a Velbus light.""" + self._velbus = velbus + self._name = light[CONF_NAME] + self._module = light['module'] + self._channel = light['channel'] + self._state = False + + @asyncio.coroutine + def async_added_to_hass(self): + """Add listener for Velbus messages on bus.""" + def _init_velbus(): + """Initialize Velbus on startup.""" + self._velbus.subscribe(self._on_message) + self.get_status() + + yield from self.hass.async_add_job(_init_velbus) + + def _on_message(self, message): + import velbus + if isinstance(message, velbus.RelayStatusMessage) and \ + message.address == self._module and \ + message.channel == self._channel: + self._state = message.is_on() + self.schedule_update_ha_state() + + @property + def name(self): + """Return the display name of this light.""" + return self._name + + @property + def should_poll(self): + """Disable polling.""" + return False + + @property + def is_on(self): + """Return true if the light is on.""" + return self._state + + def turn_on(self, **kwargs): + """Instruct the light to turn on.""" + import velbus + message = velbus.SwitchRelayOnMessage() + message.set_defaults(self._module) + message.relay_channels = [self._channel] + self._velbus.send(message) + + def turn_off(self, **kwargs): + """Instruct the light to turn off.""" + import velbus + message = velbus.SwitchRelayOffMessage() + message.set_defaults(self._module) + message.relay_channels = [self._channel] + self._velbus.send(message) + + def get_status(self): + """Retrieve current status.""" + import velbus + message = velbus.ModuleStatusRequestMessage() + message.set_defaults(self._module) + message.channels = [self._channel] + self._velbus.send(message) diff --git a/homeassistant/components/switch/velbus.py b/homeassistant/components/switch/velbus.py new file mode 100644 index 00000000000..15090091a52 --- /dev/null +++ b/homeassistant/components/switch/velbus.py @@ -0,0 +1,111 @@ +""" +Support for Velbus switches. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/switch.velbus/ +""" + +import asyncio +import logging + +import voluptuous as vol + +from homeassistant.const import CONF_NAME, CONF_DEVICES +from homeassistant.components.switch import SwitchDevice, PLATFORM_SCHEMA +from homeassistant.components.velbus import DOMAIN +import homeassistant.helpers.config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +SWITCH_SCHEMA = { + vol.Required('module'): cv.positive_int, + vol.Required('channel'): cv.positive_int, + vol.Required(CONF_NAME): cv.string +} + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_DEVICES): + vol.All(cv.ensure_list, [SWITCH_SCHEMA]) +}) + +DEPENDENCIES = ['velbus'] + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the Switch.""" + velbus = hass.data[DOMAIN] + devices = [] + + for switch in config[CONF_DEVICES]: + devices.append(VelbusSwitch(switch, velbus)) + add_devices(devices) + return True + + +class VelbusSwitch(SwitchDevice): + """Representation of a switch.""" + + def __init__(self, switch, velbus): + """Initialize a Velbus switch.""" + self._velbus = velbus + self._name = switch[CONF_NAME] + self._module = switch['module'] + self._channel = switch['channel'] + self._state = False + + @asyncio.coroutine + def async_added_to_hass(self): + """Add listener for Velbus messages on bus.""" + def _init_velbus(): + """Initialize Velbus on startup.""" + self._velbus.subscribe(self._on_message) + self.get_status() + + yield from self.hass.async_add_job(_init_velbus) + + def _on_message(self, message): + import velbus + if isinstance(message, velbus.RelayStatusMessage) and \ + message.address == self._module and \ + message.channel == self._channel: + self._state = message.is_on() + self.schedule_update_ha_state() + + @property + def name(self): + """Return the display name of this switch.""" + return self._name + + @property + def should_poll(self): + """Disable polling.""" + return False + + @property + def is_on(self): + """Return true if the switch is on.""" + return self._state + + def turn_on(self, **kwargs): + """Instruct the switch to turn on.""" + import velbus + message = velbus.SwitchRelayOnMessage() + message.set_defaults(self._module) + message.relay_channels = [self._channel] + self._velbus.send(message) + + def turn_off(self, **kwargs): + """Instruct the switch to turn off.""" + import velbus + message = velbus.SwitchRelayOffMessage() + message.set_defaults(self._module) + message.relay_channels = [self._channel] + self._velbus.send(message) + + def get_status(self): + """Retrieve current status.""" + import velbus + message = velbus.ModuleStatusRequestMessage() + message.set_defaults(self._module) + message.channels = [self._channel] + self._velbus.send(message) diff --git a/homeassistant/components/velbus.py b/homeassistant/components/velbus.py new file mode 100644 index 00000000000..ff2db955d31 --- /dev/null +++ b/homeassistant/components/velbus.py @@ -0,0 +1,43 @@ +""" +Support for Velbus platform. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/velbus/ +""" +import logging +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.const import EVENT_HOMEASSISTANT_STOP, CONF_PORT + +REQUIREMENTS = ['python-velbus==2.0.11'] + +_LOGGER = logging.getLogger(__name__) + +DOMAIN = 'velbus' + + +VELBUS_MESSAGE = 'velbus.message' + +CONFIG_SCHEMA = vol.Schema({ + DOMAIN: vol.Schema({ + vol.Required(CONF_PORT): cv.string, + }) +}, extra=vol.ALLOW_EXTRA) + + +def setup(hass, config): + """Set up the Velbus platform.""" + import velbus + port = config[DOMAIN].get(CONF_PORT) + connection = velbus.VelbusUSBConnection(port) + controller = velbus.Controller(connection) + hass.data[DOMAIN] = controller + + def stop_velbus(event): + """Disconnect from serial port.""" + _LOGGER.debug("Shutting down ") + connection.stop() + + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_velbus) + return True diff --git a/requirements_all.txt b/requirements_all.txt index 9820d0888cd..aad16af8592 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -761,6 +761,9 @@ python-telegram-bot==6.1.0 # homeassistant.components.sensor.twitch python-twitch==1.3.0 +# homeassistant.components.velbus +python-velbus==2.0.11 + # homeassistant.components.media_player.vlc python-vlc==1.1.2 From abcfcdd8872dfe36c3a96afafdb4ba7f6abeb47d Mon Sep 17 00:00:00 2001 From: Boyi C Date: Wed, 26 Jul 2017 22:46:21 +0800 Subject: [PATCH 098/118] Yahoo Weather update, supports forecast for more days (#8626) * work on weather panel * update yahooweather with more forecast details * Update yweather to allow user input forecast date * fix for houndci * fix long line * fix1 * Revert "work on weather panel" This reverts commit 28b4972233de42617fb05df574de22743604edfd. revert unintentional submodule change * fix2 fix typo, add try catch to another int() * fix pylint * fix3 * fix4 * Update yweather.py * Update yweather.py * Remove global data construct * Yahoo API support only 5 days forecast * remove forecast * fix lint * fix lint p2 * Update yweather.py --- homeassistant/components/weather/yweather.py | 64 +++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/homeassistant/components/weather/yweather.py b/homeassistant/components/weather/yweather.py index 0e216273d65..687d919ed95 100644 --- a/homeassistant/components/weather/yweather.py +++ b/homeassistant/components/weather/yweather.py @@ -11,17 +11,21 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.components.weather import ( - WeatherEntity, PLATFORM_SCHEMA, ATTR_FORECAST_TEMP) + WeatherEntity, PLATFORM_SCHEMA, + ATTR_FORECAST_TEMP, ATTR_FORECAST_TIME) from homeassistant.const import (TEMP_CELSIUS, CONF_NAME, STATE_UNKNOWN) REQUIREMENTS = ["yahooweather==0.8"] _LOGGER = logging.getLogger(__name__) +DATA_CONDITION = 'yahoo_condition' + ATTR_FORECAST_CONDITION = 'condition' ATTRIBUTION = "Weather details provided by Yahoo! Inc." -CONF_FORECAST = 'forecast' +ATTR_FORECAST_TEMP_LOW = 'templow' + CONF_WOEID = 'woeid' DEFAULT_NAME = 'Yweather' @@ -33,23 +37,22 @@ CONDITION_CLASSES = { 'fog': [19, 20, 21, 22, 23], 'hail': [17, 18, 35], 'lightning': [37], - 'lightning-rainy': [38, 39], + 'lightning-rainy': [38, 39, 47], 'partlycloudy': [44], 'pouring': [40, 45], 'rainy': [9, 11, 12], 'snowy': [8, 13, 14, 15, 16, 41, 42, 43], - 'snowy-rainy': [5, 6, 7, 10, 46, 47], - 'sunny': [32], + 'snowy-rainy': [5, 6, 7, 10, 46], + 'sunny': [32, 33, 34], 'windy': [24], 'windy-variant': [], 'exceptional': [0, 1, 2, 3, 4, 25, 36], } + PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_WOEID, default=None): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_FORECAST, default=0): - vol.All(vol.Coerce(int), vol.Range(min=0, max=5)), }) @@ -59,7 +62,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): unit = hass.config.units.temperature_unit woeid = config.get(CONF_WOEID) - forecast = config.get(CONF_FORECAST) name = config.get(CONF_NAME) yunit = UNIT_C if unit == TEMP_CELSIUS else UNIT_F @@ -77,22 +79,23 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.critical("Can't retrieve weather data from Yahoo!") return False - if forecast >= len(yahoo_api.yahoo.Forecast): - _LOGGER.error("Yahoo! only support %d days forecast", - len(yahoo_api.yahoo.Forecast)) - return False + # create condition helper + if DATA_CONDITION not in hass.data: + hass.data[DATA_CONDITION] = [str(x) for x in range(0, 50)] + for cond, condlst in CONDITION_CLASSES.items(): + for condi in condlst: + hass.data[DATA_CONDITION][condi] = cond - add_devices([YahooWeatherWeather(yahoo_api, name, forecast)], True) + add_devices([YahooWeatherWeather(yahoo_api, name)], True) class YahooWeatherWeather(WeatherEntity): """Representation of Yahoo! weather data.""" - def __init__(self, weather_data, name, forecast): + def __init__(self, weather_data, name): """Initialize the sensor.""" self._name = name self._data = weather_data - self._forecast = forecast @property def name(self): @@ -103,9 +106,9 @@ class YahooWeatherWeather(WeatherEntity): def condition(self): """Return the current condition.""" try: - return [k for k, v in CONDITION_CLASSES.items() if - int(self._data.yahoo.Now['code']) in v][0] - except IndexError: + return self.hass.data[DATA_CONDITION][int( + self._data.yahoo.Now['code'])] + except (ValueError, IndexError): return STATE_UNKNOWN @property @@ -138,6 +141,11 @@ class YahooWeatherWeather(WeatherEntity): """Return the wind speed.""" return self._data.yahoo.Wind['speed'] + @property + def wind_bearing(self): + """Return the wind direction.""" + return self._data.yahoo.Wind['direction'] + @property def attribution(self): """Return the attribution.""" @@ -147,19 +155,17 @@ class YahooWeatherWeather(WeatherEntity): def forecast(self): """Return the forecast array.""" try: - forecast_condition = \ - [k for k, v in CONDITION_CLASSES.items() if - int(self._data.yahoo.Forecast[self._forecast]['code']) - in v][0] - except IndexError: + return [ + { + ATTR_FORECAST_TIME: v['date'], + ATTR_FORECAST_TEMP:int(v['high']), + ATTR_FORECAST_TEMP_LOW: int(v['low']), + ATTR_FORECAST_CONDITION: + self.hass.data[DATA_CONDITION][int(v['code'])] + } for v in self._data.yahoo.Forecast] + except (ValueError, IndexError): return STATE_UNKNOWN - return [{ - ATTR_FORECAST_CONDITION: forecast_condition, - ATTR_FORECAST_TEMP: - self._data.yahoo.Forecast[self._forecast]['high'], - }] - def update(self): """Get the latest data from Yahoo! and updates the states.""" self._data.update() From 438edc5ca115a3a02bbc3887bdaafaf8ab24eb8e Mon Sep 17 00:00:00 2001 From: Greg Laabs Date: Wed, 26 Jul 2017 08:22:01 -0700 Subject: [PATCH 099/118] History performance improvements for single-entity requests (#8632) * Bugfix: remove superfluous domain filter This filter is already applied later in the function by the `filters` object, where it is conditionally applied when appropriate. This fixes the problem where we get a domain filter even when searching for a single entity_id, which needlessly harms the query's performance. * Performance: build different query when only getting single entity When querying the history of a single entity, we can use an entirely different method for the "synthetic zero data point" by simply sorting by date and doing a LIMIT 1. This performs thousands of times better than the multi-entity query when the current recorder_run has been going for a while. * Add entity_id filter to single-entity request The entity_id filter was handled inside the `filters.apply` logic which is used in most cases, BUT didn't work when no `filters` was passed in to the method. Now it'll work even if no `filters` object is passed in. * Fix linting errors in history.py * Undo removal of domain filter Putting back the domain filter that was removed in 76a6371705dcd57483e55dcc03435ae867c184d2 - there are use-cases where get_states is called without a filter object, so we need the domain filter to work in those cases as well. * Fix truncated comment --- homeassistant/components/history.py | 45 ++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/history.py b/homeassistant/components/history.py index 9800a15c16b..893ff23df35 100644 --- a/homeassistant/components/history.py +++ b/homeassistant/components/history.py @@ -119,19 +119,42 @@ def get_states(hass, utc_point_in_time, entity_ids=None, run=None, from sqlalchemy import and_, func with session_scope(hass=hass) as session: - most_recent_state_ids = session.query( - func.max(States.state_id).label('max_state_id') - ).filter( - (States.created >= run.start) & - (States.created < utc_point_in_time) & - (~States.domain.in_(IGNORE_DOMAINS))) + if entity_ids and len(entity_ids) == 1: + # Use an entirely different (and extremely fast) query if we only + # have a single entity id + most_recent_state_ids = session.query( + States.state_id.label('max_state_id') + ).filter( + (States.created < utc_point_in_time) & + (States.entity_id.in_(entity_ids)) + ).order_by( + States.created.desc()) - if filters: - most_recent_state_ids = filters.apply(most_recent_state_ids, - entity_ids) + if filters: + most_recent_state_ids = filters.apply(most_recent_state_ids, + entity_ids) - most_recent_state_ids = most_recent_state_ids.group_by( - States.entity_id).subquery() + most_recent_state_ids = most_recent_state_ids.limit(1) + + else: + # We have more than one entity to look at (most commonly we want + # all entities,) so we need to do a search on all states since the + # last recorder run started. + most_recent_state_ids = session.query( + func.max(States.state_id).label('max_state_id') + ).filter( + (States.created >= run.start) & + (States.created < utc_point_in_time) & + (~States.domain.in_(IGNORE_DOMAINS))) + + if filters: + most_recent_state_ids = filters.apply(most_recent_state_ids, + entity_ids) + + most_recent_state_ids = most_recent_state_ids.group_by( + States.entity_id) + + most_recent_state_ids = most_recent_state_ids.subquery() query = session.query(States).join(most_recent_state_ids, and_( States.state_id == most_recent_state_ids.c.max_state_id)) From 3318f02664fb46b3ce7de758984414d1256dd94b Mon Sep 17 00:00:00 2001 From: Jeff Wilson Date: Wed, 26 Jul 2017 11:22:31 -0400 Subject: [PATCH 100/118] Add transition support to light.zha (#8548) * Add transition support to light.zha * Address hound formatting * Address hound comments Look, nobody is perfect... alright? * Update zha.py --- homeassistant/components/light/zha.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/light/zha.py b/homeassistant/components/light/zha.py index 619723d3168..2a3ce18d74e 100644 --- a/homeassistant/components/light/zha.py +++ b/homeassistant/components/light/zha.py @@ -9,11 +9,14 @@ import logging from homeassistant.components import light, zha from homeassistant.util.color import color_RGB_to_xy +from homeassistant.const import STATE_UNKNOWN _LOGGER = logging.getLogger(__name__) DEPENDENCIES = ['zha'] +DEFAULT_DURATION = 0.5 + @asyncio.coroutine def async_setup_platform(hass, config, async_add_devices, discovery_info=None): @@ -48,6 +51,7 @@ class Light(zha.Entity, light.Light): import bellows.zigbee.zcl.clusters as zcl_clusters if zcl_clusters.general.LevelControl.cluster_id in self._in_clusters: self._supported_features |= light.SUPPORT_BRIGHTNESS + self._supported_features |= light.SUPPORT_TRANSITION self._brightness = 0 if zcl_clusters.lighting.Color.cluster_id in self._in_clusters: # Not sure all color lights necessarily support this directly @@ -62,14 +66,15 @@ class Light(zha.Entity, light.Light): @property def is_on(self) -> bool: """Return true if entity is on.""" - if self._state == 'unknown': + if self._state == STATE_UNKNOWN: return False return bool(self._state) @asyncio.coroutine def async_turn_on(self, **kwargs): """Turn the entity on.""" - duration = 5 # tenths of s + duration = kwargs.get(light.ATTR_TRANSITION, DEFAULT_DURATION) + duration = duration * 10 # tenths of s if light.ATTR_COLOR_TEMP in kwargs: temperature = kwargs[light.ATTR_COLOR_TEMP] yield from self._endpoint.light_color.move_to_color_temp( @@ -91,7 +96,8 @@ class Light(zha.Entity, light.Light): ) if self._brightness is not None: - brightness = kwargs.get('brightness', self._brightness or 255) + brightness = kwargs.get( + light.ATTR_BRIGHTNESS, self._brightness or 255) self._brightness = brightness # Move to level with on/off: yield from self._endpoint.level.move_to_level_with_on_off( From 3b4ea864a10c6923bec25e643d6d27ba022a7832 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 26 Jul 2017 20:49:52 +0100 Subject: [PATCH 101/118] Add uk_transport component. (#8600) --- .../components/sensor/uk_transport.py | 275 ++++++++++ tests/components/sensor/test_uk_transport.py | 93 ++++ tests/fixtures/uk_transport_bus.json | 110 ++++ tests/fixtures/uk_transport_train.json | 511 ++++++++++++++++++ 4 files changed, 989 insertions(+) create mode 100644 homeassistant/components/sensor/uk_transport.py create mode 100644 tests/components/sensor/test_uk_transport.py create mode 100644 tests/fixtures/uk_transport_bus.json create mode 100644 tests/fixtures/uk_transport_train.json diff --git a/homeassistant/components/sensor/uk_transport.py b/homeassistant/components/sensor/uk_transport.py new file mode 100644 index 00000000000..b9ce98ec257 --- /dev/null +++ b/homeassistant/components/sensor/uk_transport.py @@ -0,0 +1,275 @@ +"""Support for UK public transport data provided by transportapi.com. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.uk_transport/ +""" +import logging +import re +from datetime import datetime, timedelta +import requests +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle +import homeassistant.helpers.config_validation as cv + +_LOGGER = logging.getLogger(__name__) + +ATTR_ATCOCODE = 'atcocode' +ATTR_LOCALITY = 'locality' +ATTR_STOP_NAME = 'stop_name' +ATTR_REQUEST_TIME = 'request_time' +ATTR_NEXT_BUSES = 'next_buses' +ATTR_STATION_CODE = 'station_code' +ATTR_CALLING_AT = 'calling_at' +ATTR_NEXT_TRAINS = 'next_trains' + +CONF_API_APP_KEY = 'app_key' +CONF_API_APP_ID = 'app_id' +CONF_QUERIES = 'queries' +CONF_MODE = 'mode' +CONF_ORIGIN = 'origin' +CONF_DESTINATION = 'destination' + +_QUERY_SCHEME = vol.Schema({ + vol.Required(CONF_MODE): + vol.All(cv.ensure_list, [vol.In(list(['bus', 'train']))]), + vol.Required(CONF_ORIGIN): cv.string, + vol.Required(CONF_DESTINATION): cv.string, +}) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_API_APP_ID): cv.string, + vol.Required(CONF_API_APP_KEY): cv.string, + vol.Required(CONF_QUERIES): [_QUERY_SCHEME], +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Get the uk_transport sensor.""" + sensors = [] + number_sensors = len(config.get(CONF_QUERIES)) + interval = timedelta(seconds=87*number_sensors) + + for query in config.get(CONF_QUERIES): + if 'bus' in query.get(CONF_MODE): + stop_atcocode = query.get(CONF_ORIGIN) + bus_direction = query.get(CONF_DESTINATION) + sensors.append( + UkTransportLiveBusTimeSensor( + config.get(CONF_API_APP_ID), + config.get(CONF_API_APP_KEY), + stop_atcocode, + bus_direction, + interval)) + + elif 'train' in query.get(CONF_MODE): + station_code = query.get(CONF_ORIGIN) + calling_at = query.get(CONF_DESTINATION) + sensors.append( + UkTransportLiveTrainTimeSensor( + config.get(CONF_API_APP_ID), + config.get(CONF_API_APP_KEY), + station_code, + calling_at, + interval)) + + add_devices(sensors, True) + + +class UkTransportSensor(Entity): + """ + Sensor that reads the UK transport web API. + + transportapi.com provides comprehensive transport data for UK train, tube + and bus travel across the UK via simple JSON API. Subclasses of this + base class can be used to access specific types of information. + """ + + TRANSPORT_API_URL_BASE = "https://transportapi.com/v3/uk/" + ICON = 'mdi:train' + + def __init__(self, name, api_app_id, api_app_key, url): + """Initialize the sensor.""" + self._data = {} + self._api_app_id = api_app_id + self._api_app_key = api_app_key + self._url = self.TRANSPORT_API_URL_BASE + url + self._name = name + self._state = None + + @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 "min" + + @property + def icon(self): + """Icon to use in the frontend, if any.""" + return self.ICON + + def _do_api_request(self, params): + """Perform an API request.""" + request_params = dict({ + 'app_id': self._api_app_id, + 'app_key': self._api_app_key, + }, **params) + + response = requests.get(self._url, params=request_params) + if response.status_code != 200: + _LOGGER.warning('Invalid response from API') + elif 'error' in response.json(): + if 'exceeded' in response.json()['error']: + self._state = 'Useage limites exceeded' + if 'invalid' in response.json()['error']: + self._state = 'Credentials invalid' + else: + self._data = response.json() + + +class UkTransportLiveBusTimeSensor(UkTransportSensor): + """Live bus time sensor from UK transportapi.com.""" + + ICON = 'mdi:bus' + + def __init__(self, api_app_id, api_app_key, + stop_atcocode, bus_direction, interval): + """Construct a live bus time sensor.""" + self._stop_atcocode = stop_atcocode + self._bus_direction = bus_direction + self._next_buses = [] + self._destination_re = re.compile( + '{}'.format(bus_direction), re.IGNORECASE + ) + + sensor_name = 'Next bus to {}'.format(bus_direction) + stop_url = 'bus/stop/{}/live.json'.format(stop_atcocode) + + UkTransportSensor.__init__( + self, sensor_name, api_app_id, api_app_key, stop_url + ) + self.update = Throttle(interval)(self._update) + + def _update(self): + """Get the latest live departure data for the specified stop.""" + params = {'group': 'route', 'nextbuses': 'no'} + + self._do_api_request(params) + + if self._data != {}: + self._next_buses = [] + + for (route, departures) in self._data['departures'].items(): + for departure in departures: + if self._destination_re.search(departure['direction']): + self._next_buses.append({ + 'route': route, + 'direction': departure['direction'], + 'scheduled': departure['aimed_departure_time'], + 'estimated': departure['best_departure_estimate'] + }) + + self._state = min(map( + _delta_mins, [bus['scheduled'] for bus in self._next_buses] + )) + + @property + def device_state_attributes(self): + """Return other details about the sensor state.""" + attrs = {} + if self._data is not None: + for key in [ + ATTR_ATCOCODE, ATTR_LOCALITY, ATTR_STOP_NAME, + ATTR_REQUEST_TIME + ]: + attrs[key] = self._data.get(key) + attrs[ATTR_NEXT_BUSES] = self._next_buses + return attrs + + +class UkTransportLiveTrainTimeSensor(UkTransportSensor): + """Live train time sensor from UK transportapi.com.""" + + ICON = 'mdi:train' + + def __init__(self, api_app_id, api_app_key, + station_code, calling_at, interval): + """Construct a live bus time sensor.""" + self._station_code = station_code + self._calling_at = calling_at + self._next_trains = [] + + sensor_name = 'Next train to {}'.format(calling_at) + query_url = 'train/station/{}/live.json'.format(station_code) + + UkTransportSensor.__init__( + self, sensor_name, api_app_id, api_app_key, query_url + ) + self.update = Throttle(interval)(self._update) + + def _update(self): + """Get the latest live departure data for the specified stop.""" + params = {'darwin': 'false', + 'calling_at': self._calling_at, + 'train_status': 'passenger'} + + self._do_api_request(params) + self._next_trains = [] + + if self._data != {}: + if self._data['departures']['all'] == []: + self._state = 'No departures' + else: + for departure in self._data['departures']['all']: + self._next_trains.append({ + 'origin_name': departure['origin_name'], + 'destination_name': departure['destination_name'], + 'status': departure['status'], + 'scheduled': departure['aimed_departure_time'], + 'estimated': departure['expected_departure_time'], + 'platform': departure['platform'], + 'operator_name': departure['operator_name'] + }) + + self._state = min(map( + _delta_mins, + [train['scheduled'] for train in self._next_trains] + )) + + @property + def device_state_attributes(self): + """Return other details about the sensor state.""" + attrs = {} + if self._data is not None: + attrs[ATTR_STATION_CODE] = self._station_code + attrs[ATTR_CALLING_AT] = self._calling_at + if self._next_trains: + attrs[ATTR_NEXT_TRAINS] = self._next_trains + return attrs + + +def _delta_mins(hhmm_time_str): + """Calculate time delta in minutes to a time in hh:mm format.""" + now = datetime.now() + hhmm_time = datetime.strptime(hhmm_time_str, '%H:%M') + + hhmm_datetime = datetime( + now.year, now.month, now.day, + hour=hhmm_time.hour, minute=hhmm_time.minute + ) + if hhmm_datetime < now: + hhmm_datetime += timedelta(days=1) + + delta_mins = (hhmm_datetime - now).seconds // 60 + return delta_mins diff --git a/tests/components/sensor/test_uk_transport.py b/tests/components/sensor/test_uk_transport.py new file mode 100644 index 00000000000..b051d8e1a1b --- /dev/null +++ b/tests/components/sensor/test_uk_transport.py @@ -0,0 +1,93 @@ +"""The tests for the uk_transport platform.""" +import re + +import requests_mock +import unittest + +from homeassistant.components.sensor.uk_transport import ( + UkTransportSensor, + ATTR_ATCOCODE, ATTR_LOCALITY, ATTR_STOP_NAME, ATTR_NEXT_BUSES, + ATTR_STATION_CODE, ATTR_CALLING_AT, ATTR_NEXT_TRAINS, + CONF_API_APP_KEY, CONF_API_APP_ID) +from homeassistant.setup import setup_component +from tests.common import load_fixture, get_test_home_assistant + +BUS_ATCOCODE = '340000368SHE' +BUS_DIRECTION = 'Wantage' +TRAIN_STATION_CODE = 'WIM' +TRAIN_DESTINATION_NAME = 'WAT' + +VALID_CONFIG = { + 'platform': 'uk_transport', + CONF_API_APP_ID: 'foo', + CONF_API_APP_KEY: 'ebcd1234', + 'queries': [{ + 'mode': 'bus', + 'origin': BUS_ATCOCODE, + 'destination': BUS_DIRECTION}, + { + 'mode': 'train', + 'origin': TRAIN_STATION_CODE, + 'destination': TRAIN_DESTINATION_NAME}] + } + + +class TestUkTransportSensor(unittest.TestCase): + """Test the uk_transport platform.""" + + def setUp(self): + """Initialize values for this testcase class.""" + self.hass = get_test_home_assistant() + self.config = VALID_CONFIG + + def tearDown(self): + """Stop everything that was started.""" + self.hass.stop() + + @requests_mock.Mocker() + def test_bus(self, mock_req): + """Test for operational uk_transport sensor with proper attributes.""" + with requests_mock.Mocker() as mock_req: + uri = re.compile(UkTransportSensor.TRANSPORT_API_URL_BASE + '*') + mock_req.get(uri, text=load_fixture('uk_transport_bus.json')) + self.assertTrue( + setup_component(self.hass, 'sensor', {'sensor': self.config})) + + bus_state = self.hass.states.get('sensor.next_bus_to_wantage') + + assert type(bus_state.state) == str + assert bus_state.name == 'Next bus to {}'.format(BUS_DIRECTION) + assert bus_state.attributes.get(ATTR_ATCOCODE) == BUS_ATCOCODE + assert bus_state.attributes.get(ATTR_LOCALITY) == 'Harwell Campus' + assert bus_state.attributes.get(ATTR_STOP_NAME) == 'Bus Station' + assert len(bus_state.attributes.get(ATTR_NEXT_BUSES)) == 2 + + direction_re = re.compile(BUS_DIRECTION) + for bus in bus_state.attributes.get(ATTR_NEXT_BUSES): + print(bus['direction'], direction_re.match(bus['direction'])) + assert direction_re.search(bus['direction']) is not None + + @requests_mock.Mocker() + def test_train(self, mock_req): + """Test for operational uk_transport sensor with proper attributes.""" + with requests_mock.Mocker() as mock_req: + uri = re.compile(UkTransportSensor.TRANSPORT_API_URL_BASE + '*') + mock_req.get(uri, text=load_fixture('uk_transport_train.json')) + self.assertTrue( + setup_component(self.hass, 'sensor', {'sensor': self.config})) + + train_state = self.hass.states.get('sensor.next_train_to_WAT') + + assert type(train_state.state) == str + assert train_state.name == 'Next train to {}'.format( + TRAIN_DESTINATION_NAME) + assert train_state.attributes.get( + ATTR_STATION_CODE) == TRAIN_STATION_CODE + assert train_state.attributes.get( + ATTR_CALLING_AT) == TRAIN_DESTINATION_NAME + assert len(train_state.attributes.get(ATTR_NEXT_TRAINS)) == 25 + + assert train_state.attributes.get( + ATTR_NEXT_TRAINS)[0]['destination_name'] == 'London Waterloo' + assert train_state.attributes.get( + ATTR_NEXT_TRAINS)[0]['estimated'] == '06:13' diff --git a/tests/fixtures/uk_transport_bus.json b/tests/fixtures/uk_transport_bus.json new file mode 100644 index 00000000000..5e1e27a4ba3 --- /dev/null +++ b/tests/fixtures/uk_transport_bus.json @@ -0,0 +1,110 @@ +{ + "atcocode": "340000368SHE", + "bearing": "", + "departures": { + "32A": [{ + "aimed_departure_time": "10:18", + "best_departure_estimate": "10:18", + "date": "2017-05-09", + "dir": "outbound", + "direction": "Market Place (Wantage)", + "expected_departure_date": null, + "expected_departure_time": null, + "id": "https://transportapi.com/v3/uk/bus/route/THTR/32A/outbound/340000368SHE/2017-05-09/10:18/timetable.json?app_id=e99&app_key=058", + "line": "32A", + "line_name": "32A", + "mode": "bus", + "operator": "THTR", + "operator_name": "Thames Travel", + "source": "Traveline timetable (not a nextbuses live region)" + }, + { + "aimed_departure_time": "11:00", + "best_departure_estimate": "11:00", + "date": "2017-05-09", + "dir": "outbound", + "direction": "Stratton Way (Abingdon Town Centre)", + "expected_departure_date": null, + "expected_departure_time": null, + "id": "https://transportapi.com/v3/uk/bus/route/THTR/32A/outbound/340000368SHE/2017-05-09/11:00/timetable.json?app_id=e99&app_key=058", + "line": "32A", + "line_name": "32A", + "mode": "bus", + "operator": "THTR", + "operator_name": "Thames Travel", + "source": "Traveline timetable (not a nextbuses live region)" + }, + { + "aimed_departure_time": "11:18", + "best_departure_estimate": "11:18", + "date": "2017-05-09", + "dir": "outbound", + "direction": "Market Place (Wantage)", + "expected_departure_date": null, + "expected_departure_time": null, + "id": "https://transportapi.com/v3/uk/bus/route/THTR/32A/outbound/340000368SHE/2017-05-09/11:18/timetable.json?app_id=e99&app_key=058", + "line": "32A", + "line_name": "32A", + "mode": "bus", + "operator": "THTR", + "operator_name": "Thames Travel", + "source": "Traveline timetable (not a nextbuses live region)" + } + ], + "X32": [{ + "aimed_departure_time": "10:09", + "best_departure_estimate": "10:09", + "date": "2017-05-09", + "dir": "inbound", + "direction": "Parkway Station (Didcot)", + "expected_departure_date": null, + "expected_departure_time": null, + "id": "https://transportapi.com/v3/uk/bus/route/THTR/X32/inbound/340000368SHE/2017-05-09/10:09/timetable.json?app_id=e99&app_key=058", + "line": "X32", + "line_name": "X32", + "mode": "bus", + "operator": "THTR", + "operator_name": "Thames Travel", + "source": "Traveline timetable (not a nextbuses live region)" + }, + { + "aimed_departure_time": "10:30", + "best_departure_estimate": "10:30", + "date": "2017-05-09", + "dir": "inbound", + "direction": "Parks Road (Oxford City Centre)", + "expected_departure_date": null, + "expected_departure_time": null, + "id": "https://transportapi.com/v3/uk/bus/route/THTR/X32/inbound/340000368SHE/2017-05-09/10:30/timetable.json?app_id=e99&app_key=058", + "line": "X32", + "line_name": "X32", + "mode": "bus", + "operator": "THTR", + "operator_name": "Thames Travel", + "source": "Traveline timetable (not a nextbuses live region)" + }, + { + "aimed_departure_time": "10:39", + "best_departure_estimate": "10:39", + "date": "2017-05-09", + "dir": "inbound", + "direction": "Parkway Station (Didcot)", + "expected_departure_date": null, + "expected_departure_time": null, + "id": "https://transportapi.com/v3/uk/bus/route/THTR/X32/inbound/340000368SHE/2017-05-09/10:39/timetable.json?app_id=e99&app_key=058", + "line": "X32", + "line_name": "X32", + "mode": "bus", + "operator": "THTR", + "operator_name": "Thames Travel", + "source": "Traveline timetable (not a nextbuses live region)" + } + ] + }, + "indicator": "in", + "locality": "Harwell Campus", + "name": "Bus Station (in)", + "request_time": "2017-05-09T10:03:41+01:00", + "smscode": "oxfajwgp", + "stop_name": "Bus Station" +} diff --git a/tests/fixtures/uk_transport_train.json b/tests/fixtures/uk_transport_train.json new file mode 100644 index 00000000000..b06e8db6ca7 --- /dev/null +++ b/tests/fixtures/uk_transport_train.json @@ -0,0 +1,511 @@ +{ + "date": "2017-07-10", + "time_of_day": "06:10", + "request_time": "2017-07-10T06:10:05+01:00", + "station_name": "Wimbledon", + "station_code": "WIM", + "departures": { + "all": [ + { + "mode": "train", + "service": "24671405", + "train_uid": "W36814", + "platform": "8", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:13", + "aimed_arrival_time": null, + "aimed_pass_time": null, + "origin_name": "Wimbledon", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "STARTS HERE", + "expected_arrival_time": null, + "expected_departure_time": "06:13", + "best_arrival_estimate_mins": null, + "best_departure_estimate_mins": 2 + }, + { + "mode": "train", + "service": "24673205", + "train_uid": "W36613", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:14", + "aimed_arrival_time": "06:13", + "aimed_pass_time": null, + "origin_name": "Hampton Court", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "EARLY", + "expected_arrival_time": "06:13", + "expected_departure_time": "06:14", + "best_arrival_estimate_mins": 2, + "best_departure_estimate_mins": 3 + }, + { + "mode": "train", + "service": "24673505", + "train_uid": "W36012", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:20", + "aimed_arrival_time": "06:20", + "aimed_pass_time": null, + "origin_name": "Guildford", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "06:20", + "expected_departure_time": "06:20", + "best_arrival_estimate_mins": 9, + "best_departure_estimate_mins": 9 + }, + { + "mode": "train", + "service": "24673305", + "train_uid": "W34087", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:23", + "aimed_arrival_time": "06:23", + "aimed_pass_time": null, + "origin_name": "Dorking", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "XX", + "status": "ON TIME", + "expected_arrival_time": "06:23", + "expected_departure_time": "06:23", + "best_arrival_estimate_mins": 12, + "best_departure_estimate_mins": 12 + }, + { + "mode": "train", + "service": "24671505", + "train_uid": "W37471", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:32", + "aimed_arrival_time": "06:31", + "aimed_pass_time": null, + "origin_name": "London Waterloo", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "06:31", + "expected_departure_time": "06:32", + "best_arrival_estimate_mins": 20, + "best_departure_estimate_mins": 21 + }, + { + "mode": "train", + "service": "24673605", + "train_uid": "W35790", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:35", + "aimed_arrival_time": "06:35", + "aimed_pass_time": null, + "origin_name": "Woking", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "06:35", + "expected_departure_time": "06:35", + "best_arrival_estimate_mins": 24, + "best_departure_estimate_mins": 24 + }, + { + "mode": "train", + "service": "24673705", + "train_uid": "W35665", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:38", + "aimed_arrival_time": "06:38", + "aimed_pass_time": null, + "origin_name": "Epsom", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "06:38", + "expected_departure_time": "06:38", + "best_arrival_estimate_mins": 27, + "best_departure_estimate_mins": 27 + }, + { + "mode": "train", + "service": "24671405", + "train_uid": "W36816", + "platform": "8", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:43", + "aimed_arrival_time": "06:43", + "aimed_pass_time": null, + "origin_name": "London Waterloo", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "06:43", + "expected_departure_time": "06:43", + "best_arrival_estimate_mins": 32, + "best_departure_estimate_mins": 32 + }, + { + "mode": "train", + "service": "24673205", + "train_uid": "W36618", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:44", + "aimed_arrival_time": "06:43", + "aimed_pass_time": null, + "origin_name": "Hampton Court", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "06:43", + "expected_departure_time": "06:44", + "best_arrival_estimate_mins": 32, + "best_departure_estimate_mins": 33 + }, + { + "mode": "train", + "service": "24673105", + "train_uid": "W36429", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:47", + "aimed_arrival_time": "06:46", + "aimed_pass_time": null, + "origin_name": "Shepperton", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "06:46", + "expected_departure_time": "06:47", + "best_arrival_estimate_mins": 35, + "best_departure_estimate_mins": 36 + }, + { + "mode": "train", + "service": "24629204", + "train_uid": "W36916", + "platform": "6", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:47", + "aimed_arrival_time": "06:47", + "aimed_pass_time": null, + "origin_name": "Basingstoke", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "LATE", + "expected_arrival_time": "06:48", + "expected_departure_time": "06:48", + "best_arrival_estimate_mins": 37, + "best_departure_estimate_mins": 37 + }, + { + "mode": "train", + "service": "24673505", + "train_uid": "W36016", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:50", + "aimed_arrival_time": "06:49", + "aimed_pass_time": null, + "origin_name": "Guildford", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "06:49", + "expected_departure_time": "06:50", + "best_arrival_estimate_mins": 38, + "best_departure_estimate_mins": 39 + }, + { + "mode": "train", + "service": "24673705", + "train_uid": "W35489", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:53", + "aimed_arrival_time": "06:52", + "aimed_pass_time": null, + "origin_name": "Guildford", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "EARLY", + "expected_arrival_time": "06:52", + "expected_departure_time": "06:53", + "best_arrival_estimate_mins": 41, + "best_departure_estimate_mins": 42 + }, + { + "mode": "train", + "service": "24673405", + "train_uid": "W37107", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "06:58", + "aimed_arrival_time": "06:57", + "aimed_pass_time": null, + "origin_name": "Chessington South", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "06:57", + "expected_departure_time": "06:58", + "best_arrival_estimate_mins": 46, + "best_departure_estimate_mins": 47 + }, + { + "mode": "train", + "service": "24671505", + "train_uid": "W37473", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:02", + "aimed_arrival_time": "07:01", + "aimed_pass_time": null, + "origin_name": "London Waterloo", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "EARLY", + "expected_arrival_time": "07:01", + "expected_departure_time": "07:02", + "best_arrival_estimate_mins": 50, + "best_departure_estimate_mins": 51 + }, + { + "mode": "train", + "service": "24673605", + "train_uid": "W35795", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:05", + "aimed_arrival_time": "07:04", + "aimed_pass_time": null, + "origin_name": "Woking", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "07:04", + "expected_departure_time": "07:05", + "best_arrival_estimate_mins": 53, + "best_departure_estimate_mins": 54 + }, + { + "mode": "train", + "service": "24673305", + "train_uid": "W34090", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:08", + "aimed_arrival_time": "07:07", + "aimed_pass_time": null, + "origin_name": "Dorking", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "XX", + "status": "ON TIME", + "expected_arrival_time": "07:07", + "expected_departure_time": "07:08", + "best_arrival_estimate_mins": 56, + "best_departure_estimate_mins": 57 + }, + { + "mode": "train", + "service": "24673205", + "train_uid": "W36623", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:13", + "aimed_arrival_time": "07:12", + "aimed_pass_time": null, + "origin_name": "Hampton Court", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "07:12", + "expected_departure_time": "07:13", + "best_arrival_estimate_mins": 61, + "best_departure_estimate_mins": 62 + }, + { + "mode": "train", + "service": "24671405", + "train_uid": "W36819", + "platform": "8", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:13", + "aimed_arrival_time": "07:13", + "aimed_pass_time": null, + "origin_name": "London Waterloo", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "07:13", + "expected_departure_time": "07:13", + "best_arrival_estimate_mins": 62, + "best_departure_estimate_mins": 62 + }, + { + "mode": "train", + "service": "24673105", + "train_uid": "W36434", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:16", + "aimed_arrival_time": "07:15", + "aimed_pass_time": null, + "origin_name": "Shepperton", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "07:15", + "expected_departure_time": "07:16", + "best_arrival_estimate_mins": 64, + "best_departure_estimate_mins": 65 + }, + { + "mode": "train", + "service": "24673505", + "train_uid": "W36019", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:19", + "aimed_arrival_time": "07:18", + "aimed_pass_time": null, + "origin_name": "Guildford", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "07:18", + "expected_departure_time": "07:19", + "best_arrival_estimate_mins": 67, + "best_departure_estimate_mins": 68 + }, + { + "mode": "train", + "service": "24673705", + "train_uid": "W35494", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:22", + "aimed_arrival_time": "07:21", + "aimed_pass_time": null, + "origin_name": "Guildford", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "07:21", + "expected_departure_time": "07:22", + "best_arrival_estimate_mins": 70, + "best_departure_estimate_mins": 71 + }, + { + "mode": "train", + "service": "24673205", + "train_uid": "W36810", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:25", + "aimed_arrival_time": "07:24", + "aimed_pass_time": null, + "origin_name": "Esher", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "07:24", + "expected_departure_time": "07:25", + "best_arrival_estimate_mins": 73, + "best_departure_estimate_mins": 74 + }, + { + "mode": "train", + "service": "24673405", + "train_uid": "W37112", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:28", + "aimed_arrival_time": "07:27", + "aimed_pass_time": null, + "origin_name": "Chessington South", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "07:27", + "expected_departure_time": "07:28", + "best_arrival_estimate_mins": 76, + "best_departure_estimate_mins": 77 + }, + { + "mode": "train", + "service": "24671505", + "train_uid": "W37476", + "platform": "5", + "operator": "SW", + "operator_name": "South West Trains", + "aimed_departure_time": "07:32", + "aimed_arrival_time": "07:31", + "aimed_pass_time": null, + "origin_name": "London Waterloo", + "source": "Network Rail", + "destination_name": "London Waterloo", + "category": "OO", + "status": "ON TIME", + "expected_arrival_time": "07:31", + "expected_departure_time": "07:32", + "best_arrival_estimate_mins": 80, + "best_departure_estimate_mins": 81 + } + ] + } +} From f5eeb252a74a4ae563cac2deedf93d82b73ebfa7 Mon Sep 17 00:00:00 2001 From: kfcook <809694+kfcook@users.noreply.github.com> Date: Thu, 27 Jul 2017 02:14:12 -0400 Subject: [PATCH 102/118] Added support for SerenaHoneycombShades to Lutron Caseta (#8662) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an optional extended description… --- homeassistant/components/cover/lutron_caseta.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/cover/lutron_caseta.py b/homeassistant/components/cover/lutron_caseta.py index 2c411c61ba4..6857aaebf9b 100644 --- a/homeassistant/components/cover/lutron_caseta.py +++ b/homeassistant/components/cover/lutron_caseta.py @@ -23,7 +23,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the Lutron Caseta Serena shades as a cover device.""" devs = [] bridge = hass.data[LUTRON_CASETA_SMARTBRIDGE] - cover_devices = bridge.get_devices_by_types(["SerenaRollerShade"]) + cover_devices = bridge.get_devices_by_types(["SerenaRollerShade", + "SerenaHoneycombShade"]) for cover_device in cover_devices: dev = LutronCasetaCover(cover_device, bridge) devs.append(dev) From 9d5c61b2f07574637b430b222dbb587aa783649c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ab=C3=ADlio=20Costa?= Date: Thu, 27 Jul 2017 07:24:15 +0100 Subject: [PATCH 103/118] MQTT Switch: add availability_topic for online/offline status (#8593) * mqtt switch: add availability_topic for online/offline status * fix method doc strings * MQTT Switch: add test --- homeassistant/components/mqtt/__init__.py | 1 + homeassistant/components/switch/mqtt.py | 38 ++++++++++++++++--- tests/components/switch/test_mqtt.py | 45 ++++++++++++++++++++++- 3 files changed, 77 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 3c75648892b..929ae0fc455 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -58,6 +58,7 @@ CONF_WILL_MESSAGE = 'will_message' CONF_STATE_TOPIC = 'state_topic' CONF_COMMAND_TOPIC = 'command_topic' +CONF_AVAILABILITY_TOPIC = 'availability_topic' CONF_QOS = 'qos' CONF_RETAIN = 'retain' diff --git a/homeassistant/components/switch/mqtt.py b/homeassistant/components/switch/mqtt.py index e9c282e4c45..1169e5a3d5d 100644 --- a/homeassistant/components/switch/mqtt.py +++ b/homeassistant/components/switch/mqtt.py @@ -11,7 +11,8 @@ import voluptuous as vol from homeassistant.core import callback from homeassistant.components.mqtt import ( - CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_QOS, CONF_RETAIN) + CONF_STATE_TOPIC, CONF_COMMAND_TOPIC, CONF_AVAILABILITY_TOPIC, CONF_QOS, + CONF_RETAIN) from homeassistant.components.switch import SwitchDevice from homeassistant.const import ( CONF_NAME, CONF_OPTIMISTIC, CONF_VALUE_TEMPLATE, CONF_PAYLOAD_OFF, @@ -50,6 +51,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): config.get(CONF_NAME), config.get(CONF_STATE_TOPIC), config.get(CONF_COMMAND_TOPIC), + config.get(CONF_AVAILABILITY_TOPIC), config.get(CONF_QOS), config.get(CONF_RETAIN), config.get(CONF_PAYLOAD_ON), @@ -62,13 +64,16 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): class MqttSwitch(SwitchDevice): """Representation of a switch that can be toggled using MQTT.""" - def __init__(self, name, state_topic, command_topic, qos, retain, - payload_on, payload_off, optimistic, value_template): + def __init__(self, name, state_topic, command_topic, availability_topic, + qos, retain, payload_on, payload_off, optimistic, + value_template): """Initialize the MQTT switch.""" self._state = False self._name = name self._state_topic = state_topic self._command_topic = command_topic + self._availability_topic = availability_topic + self._available = True if availability_topic is None else False self._qos = qos self._retain = retain self._payload_on = payload_on @@ -83,8 +88,8 @@ class MqttSwitch(SwitchDevice): This method is a coroutine. """ @callback - def message_received(topic, payload, qos): - """Handle new MQTT messages.""" + def state_message_received(topic, payload, qos): + """Handle new MQTT state messages.""" if self._template is not None: payload = self._template.async_render_with_possible_json_value( payload) @@ -95,12 +100,28 @@ class MqttSwitch(SwitchDevice): self.hass.async_add_job(self.async_update_ha_state()) + @callback + def availability_message_received(topic, payload, qos): + """Handle new MQTT availability messages.""" + if payload == self._payload_on: + self._available = True + elif payload == self._payload_off: + self._available = False + + self.hass.async_add_job(self.async_update_ha_state()) + if self._state_topic is None: # Force into optimistic mode. self._optimistic = True else: yield from mqtt.async_subscribe( - self.hass, self._state_topic, message_received, self._qos) + self.hass, self._state_topic, state_message_received, + self._qos) + + if self._availability_topic is not None: + yield from mqtt.async_subscribe( + self.hass, self._availability_topic, + availability_message_received, self._qos) @property def should_poll(self): @@ -112,6 +133,11 @@ class MqttSwitch(SwitchDevice): """Return the name of the switch.""" return self._name + @property + def available(self) -> bool: + """Return if switch is available.""" + return self._available + @property def is_on(self): """Return true if device is on.""" diff --git a/tests/components/switch/test_mqtt.py b/tests/components/switch/test_mqtt.py index 8215eae26cc..133978a7bd8 100644 --- a/tests/components/switch/test_mqtt.py +++ b/tests/components/switch/test_mqtt.py @@ -2,7 +2,8 @@ import unittest from homeassistant.setup import setup_component -from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ASSUMED_STATE +from homeassistant.const import STATE_ON, STATE_OFF, STATE_UNAVAILABLE,\ + ATTR_ASSUMED_STATE import homeassistant.components.switch as switch from tests.common import ( mock_mqtt_component, fire_mqtt_message, get_test_home_assistant) @@ -110,3 +111,45 @@ class TestSensorMQTT(unittest.TestCase): state = self.hass.states.get('switch.test') self.assertEqual(STATE_OFF, state.state) + + def test_controlling_availability(self): + """Test the controlling state via topic.""" + assert setup_component(self.hass, switch.DOMAIN, { + switch.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'state-topic', + 'command_topic': 'command-topic', + 'availability_topic': 'availability_topic', + 'payload_on': 1, + 'payload_off': 0 + } + }) + + state = self.hass.states.get('switch.test') + self.assertEqual(STATE_UNAVAILABLE, state.state) + + fire_mqtt_message(self.hass, 'availability_topic', '1') + self.hass.block_till_done() + + state = self.hass.states.get('switch.test') + self.assertEqual(STATE_OFF, state.state) + self.assertFalse(state.attributes.get(ATTR_ASSUMED_STATE)) + + fire_mqtt_message(self.hass, 'availability_topic', '0') + self.hass.block_till_done() + + state = self.hass.states.get('switch.test') + self.assertEqual(STATE_UNAVAILABLE, state.state) + + fire_mqtt_message(self.hass, 'state-topic', '1') + self.hass.block_till_done() + + state = self.hass.states.get('switch.test') + self.assertEqual(STATE_UNAVAILABLE, state.state) + + fire_mqtt_message(self.hass, 'availability_topic', '1') + self.hass.block_till_done() + + state = self.hass.states.get('switch.test') + self.assertEqual(STATE_ON, state.state) From 1e8c00ac021afa28488b33c0b9b4ef25cd818e61 Mon Sep 17 00:00:00 2001 From: Richard Cox Date: Wed, 26 Jul 2017 23:58:34 -0700 Subject: [PATCH 104/118] Adding support for mapping keys to value in statsd (#8665) * Adding ability to map specific states to values * Adding test for mapping --- homeassistant/components/statsd.py | 8 +++++++- tests/components/test_statsd.py | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/statsd.py b/homeassistant/components/statsd.py index 452faf8933b..3613f53c098 100644 --- a/homeassistant/components/statsd.py +++ b/homeassistant/components/statsd.py @@ -19,6 +19,7 @@ _LOGGER = logging.getLogger(__name__) CONF_ATTR = 'log_attributes' CONF_RATE = 'rate' +CONF_VALUE_MAP = 'value_mapping' DEFAULT_HOST = 'localhost' DEFAULT_PORT = 8125 @@ -34,6 +35,7 @@ CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_PREFIX, default=DEFAULT_PREFIX): cv.string, vol.Optional(CONF_RATE, default=DEFAULT_RATE): vol.All(vol.Coerce(int), vol.Range(min=1)), + vol.Optional(CONF_VALUE_MAP, default=None): dict, }), }, extra=vol.ALLOW_EXTRA) @@ -47,6 +49,7 @@ def setup(hass, config): port = conf.get(CONF_PORT) sample_rate = conf.get(CONF_RATE) prefix = conf.get(CONF_PREFIX) + value_mapping = conf.get(CONF_VALUE_MAP) show_attribute_flag = conf.get(CONF_ATTR) statsd_client = statsd.StatsClient(host=host, port=port, prefix=prefix) @@ -59,7 +62,10 @@ def setup(hass, config): return try: - _state = state_helper.state_as_number(state) + if value_mapping and state.state in value_mapping: + _state = float(value_mapping[state.state]) + else: + _state = state_helper.state_as_number(state) except ValueError: # Set the state to none and continue for any numeric attributes. _state = None diff --git a/tests/components/test_statsd.py b/tests/components/test_statsd.py index eb8933b77be..5fd907fe0b1 100644 --- a/tests/components/test_statsd.py +++ b/tests/components/test_statsd.py @@ -86,6 +86,7 @@ class TestStatsd(unittest.TestCase): config = { 'statsd': { 'host': 'host', + 'value_mapping': {'custom': 3} } } @@ -98,6 +99,7 @@ class TestStatsd(unittest.TestCase): valid = {'1': 1, '1.0': 1.0, + 'custom': 3, STATE_ON: 1, STATE_OFF: 0} for in_, out in valid.items(): From b59c29943b82bd1e791e44cb9eac27dc3f07fcef Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 27 Jul 2017 17:22:40 +0200 Subject: [PATCH 105/118] Upgrade fuzzywuzzy to 0.15.1 (#8671) --- homeassistant/components/conversation.py | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/conversation.py b/homeassistant/components/conversation.py index 303e83e7e0e..62611b82496 100644 --- a/homeassistant/components/conversation.py +++ b/homeassistant/components/conversation.py @@ -19,7 +19,7 @@ from homeassistant.helpers import intent, config_validation as cv from homeassistant.components import http -REQUIREMENTS = ['fuzzywuzzy==0.15.0'] +REQUIREMENTS = ['fuzzywuzzy==0.15.1'] DEPENDENCIES = ['http'] ATTR_TEXT = 'text' diff --git a/requirements_all.txt b/requirements_all.txt index aad16af8592..60947488fba 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -235,7 +235,7 @@ fritzhome==1.0.2 fsapi==0.0.7 # homeassistant.components.conversation -fuzzywuzzy==0.15.0 +fuzzywuzzy==0.15.1 # homeassistant.components.tts.google gTTS-token==1.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 9d2842c7bbb..8c40e75c288 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -43,7 +43,7 @@ dsmr_parser==0.8 evohomeclient==0.2.5 # homeassistant.components.conversation -fuzzywuzzy==0.15.0 +fuzzywuzzy==0.15.1 # homeassistant.components.tts.google gTTS-token==1.1.1 From 4fcaea23a840de26a6e573a00ccd494fd205f54e Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 27 Jul 2017 17:23:07 +0200 Subject: [PATCH 106/118] Upgrade libnacl to 1.5.2 (#8670) --- homeassistant/components/device_tracker/owntracks.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/device_tracker/owntracks.py b/homeassistant/components/device_tracker/owntracks.py index ab4ba315c02..b23008336ac 100644 --- a/homeassistant/components/device_tracker/owntracks.py +++ b/homeassistant/components/device_tracker/owntracks.py @@ -21,7 +21,7 @@ from homeassistant.components import zone as zone_comp from homeassistant.components.device_tracker import PLATFORM_SCHEMA DEPENDENCIES = ['mqtt'] -REQUIREMENTS = ['libnacl==1.5.1'] +REQUIREMENTS = ['libnacl==1.5.2'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 60947488fba..741ed38f47e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -353,7 +353,7 @@ keyring>=9.3,<10.0 knxip==0.5 # homeassistant.components.device_tracker.owntracks -libnacl==1.5.1 +libnacl==1.5.2 # homeassistant.components.dyson libpurecoollink==0.2.0 From 74581b57f8d04c958b3ba7a26919d7cfa90c242f Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 27 Jul 2017 17:23:51 +0200 Subject: [PATCH 107/118] Upgrade sqlalchemy to 1.1.12 (#8669) --- homeassistant/components/recorder/__init__.py | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/recorder/__init__.py b/homeassistant/components/recorder/__init__.py index 63dbf9fc1b1..77a049376e5 100644 --- a/homeassistant/components/recorder/__init__.py +++ b/homeassistant/components/recorder/__init__.py @@ -33,7 +33,7 @@ from . import purge, migration from .const import DATA_INSTANCE from .util import session_scope -REQUIREMENTS = ['sqlalchemy==1.1.11'] +REQUIREMENTS = ['sqlalchemy==1.1.12'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 741ed38f47e..a7c8ebb0f28 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -881,7 +881,7 @@ speedtest-cli==1.0.6 # homeassistant.components.recorder # homeassistant.scripts.db_migrator -sqlalchemy==1.1.11 +sqlalchemy==1.1.12 # homeassistant.components.statsd statsd==3.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 8c40e75c288..01f94812031 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -130,7 +130,7 @@ somecomfort==0.4.1 # homeassistant.components.recorder # homeassistant.scripts.db_migrator -sqlalchemy==1.1.11 +sqlalchemy==1.1.12 # homeassistant.components.statsd statsd==3.2.1 From 9e6817b6d05d656edca85ae14794787de3b11a25 Mon Sep 17 00:00:00 2001 From: Daniel Perna Date: Thu, 27 Jul 2017 17:45:59 +0200 Subject: [PATCH 108/118] Upgrade pyhomematic to 0.1.30 (#8673) --- homeassistant/components/homematic.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/homematic.py b/homeassistant/components/homematic.py index a8fc645ee4c..f9583d9be7a 100644 --- a/homeassistant/components/homematic.py +++ b/homeassistant/components/homematic.py @@ -21,7 +21,7 @@ from homeassistant.helpers.entity import Entity from homeassistant.helpers.event import track_time_interval from homeassistant.config import load_yaml_config_file -REQUIREMENTS = ['pyhomematic==0.1.29'] +REQUIREMENTS = ['pyhomematic==0.1.30'] DOMAIN = 'homematic' diff --git a/requirements_all.txt b/requirements_all.txt index a7c8ebb0f28..b6ee7eb5d06 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -590,7 +590,7 @@ pyharmony==1.0.16 pyhik==0.1.3 # homeassistant.components.homematic -pyhomematic==0.1.29 +pyhomematic==0.1.30 # homeassistant.components.sensor.hydroquebec pyhydroquebec==1.2.0 From 51108b8fe9e0718d868a464f4abd0a6c6418ce65 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Thu, 27 Jul 2017 21:23:22 +0200 Subject: [PATCH 109/118] Hass.io: logo support / timeout handling (#8668) * Disable auth on logo / no timeout for addons update/install * fix tests --- homeassistant/components/hassio.py | 35 +++++++++++++++++++++++++----- tests/components/test_hassio.py | 22 +++++++++++++++++++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/hassio.py b/homeassistant/components/hassio.py index 4ce60fed014..1ba599c72b4 100644 --- a/homeassistant/components/hassio.py +++ b/homeassistant/components/hassio.py @@ -25,8 +25,15 @@ _LOGGER = logging.getLogger(__name__) DOMAIN = 'hassio' DEPENDENCIES = ['http'] -TIMEOUT = 10 -NO_TIMEOUT = set(['homeassistant/update', 'host/update', 'supervisor/update']) +NO_TIMEOUT = { + re.compile(r'^homeassistant/update$'), re.compile(r'^host/update$'), + re.compile(r'^supervisor/update$'), re.compile(r'^addons/[^/]*/update$'), + re.compile(r'^addons/[^/]*/install$') +} + +NO_AUTH = { + re.compile(r'^panel$'), re.compile(r'^addons/[^/]*/logo$') +} @asyncio.coroutine @@ -71,7 +78,7 @@ class HassIO(object): This method is a coroutine. """ try: - with async_timeout.timeout(TIMEOUT, loop=self.loop): + with async_timeout.timeout(10, loop=self.loop): request = yield from self.websession.get( "http://{}{}".format(self._ip, "/supervisor/ping") ) @@ -97,12 +104,12 @@ class HassIO(object): This method is a coroutine. """ - read_timeout = 0 if path in NO_TIMEOUT else 300 + read_timeout = _get_timeout(path) try: data = None headers = None - with async_timeout.timeout(TIMEOUT, loop=self.loop): + with async_timeout.timeout(10, loop=self.loop): data = yield from request.read() if data: headers = {CONTENT_TYPE: request.content_type} @@ -140,7 +147,7 @@ class HassIOView(HomeAssistantView): @asyncio.coroutine def _handle(self, request, path): """Route data to hassio.""" - if path != 'panel' and not request[KEY_AUTHENTICATED]: + if _need_auth(path) and not request[KEY_AUTHENTICATED]: return web.Response(status=401) client = yield from self.hassio.command_proxy(path, request) @@ -173,3 +180,19 @@ def _create_response_log(client, data): status=client.status, content_type=CONTENT_TYPE_TEXT_PLAIN, ) + + +def _get_timeout(path): + """Return timeout for a url path.""" + for re_path in NO_TIMEOUT: + if re_path.match(path): + return 0 + return 300 + + +def _need_auth(path): + """Return if a path need a auth.""" + for re_path in NO_AUTH: + if re_path.match(path): + return False + return True diff --git a/tests/components/test_hassio.py b/tests/components/test_hassio.py index eb0754fdc0a..ccb56891495 100644 --- a/tests/components/test_hassio.py +++ b/tests/components/test_hassio.py @@ -106,6 +106,28 @@ def test_forward_request_no_auth_for_panel(hassio_client): assert mresp.mock_calls[0][1] == (response, 'data') +@asyncio.coroutine +def test_forward_request_no_auth_for_logo(hassio_client): + """Test no auth needed for .""" + response = MagicMock() + response.read.return_value = mock_coro('data') + + with patch('homeassistant.components.hassio.HassIO.command_proxy', + Mock(return_value=mock_coro(response))), \ + patch('homeassistant.components.hassio._create_response') as mresp: + mresp.return_value = 'response' + resp = yield from hassio_client.get('/api/hassio/addons/bl_b392/logo') + + # Check we got right response + assert resp.status == 200 + body = yield from resp.text() + assert body == 'response' + + # Check we forwarded command + assert len(mresp.mock_calls) == 1 + assert mresp.mock_calls[0][1] == (response, 'data') + + @asyncio.coroutine def test_forward_log_request(hassio_client): """Test fetching normal log path.""" From 0ab0e35d5985103a1056af45110461d96556eb4f Mon Sep 17 00:00:00 2001 From: Brian Gehrich Date: Thu, 27 Jul 2017 16:33:17 -0400 Subject: [PATCH 110/118] Updated pysnmp to 4.3.9 (#8675) --- homeassistant/components/device_tracker/snmp.py | 2 +- homeassistant/components/sensor/snmp.py | 2 +- requirements_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/device_tracker/snmp.py b/homeassistant/components/device_tracker/snmp.py index 46b1686b21d..3efae2b9ce2 100644 --- a/homeassistant/components/device_tracker/snmp.py +++ b/homeassistant/components/device_tracker/snmp.py @@ -16,7 +16,7 @@ from homeassistant.const import CONF_HOST _LOGGER = logging.getLogger(__name__) -REQUIREMENTS = ['pysnmp==4.3.8'] +REQUIREMENTS = ['pysnmp==4.3.9'] CONF_COMMUNITY = 'community' CONF_AUTHKEY = 'authkey' diff --git a/homeassistant/components/sensor/snmp.py b/homeassistant/components/sensor/snmp.py index 75a6f68a0a2..361ce551426 100644 --- a/homeassistant/components/sensor/snmp.py +++ b/homeassistant/components/sensor/snmp.py @@ -15,7 +15,7 @@ from homeassistant.helpers.entity import Entity from homeassistant.const import ( CONF_HOST, CONF_NAME, CONF_PORT, CONF_UNIT_OF_MEASUREMENT) -REQUIREMENTS = ['pysnmp==4.3.8'] +REQUIREMENTS = ['pysnmp==4.3.9'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index b6ee7eb5d06..5bce15dbfd2 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -684,7 +684,7 @@ pysma==0.1.3 # homeassistant.components.device_tracker.snmp # homeassistant.components.sensor.snmp -pysnmp==4.3.8 +pysnmp==4.3.9 # homeassistant.components.sensor.thinkingcleaner # homeassistant.components.switch.thinkingcleaner From e8ce41874c8b637f666ab8809ff40be75c48221e Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 27 Jul 2017 15:57:30 -0700 Subject: [PATCH 111/118] Fix COMMAND_CLASS_BARRIER_OPERATOR for dev branch of OpenZwave (#8574) * Update zwave.py to work with updated OpenZwave library Update zwave.py to work with updated OpenZwave library * Update zwave.py * Update zwave.py * Update to fix garage door openers Update to fix garage door support for latest version of openzwavelib * Update to cover.zwave list of states Update to cover.zwave to provide list of states based on dev version of openzwave lib * Some values not saved * Formatting fix * Formatting fix * Variable typo * Formatting fix * Formatting * Variable Update Variable Update and properties added * Formatting fixes * Formatting Fix * Update test case for door states * Formatting / Testing process fix * Formatting * Formatting / Test Fixes * Variable rename * Added members to CoverDevice * Removed un-needed else * Formatting * Formatting * Variable name changes and const updates * Changed variable names to cover_state * Added constains into const.py * Updated to change the main state on the cover device * Fixes * Formatting fixes * Formatting/Variables * Formatting * Variable fixes * Import update * Formatting / Variables * Update test for new states * Revert state changes * Test fix * Variable Fix * Formatting * Variable typo * Missing constant * Variable fix * Requested changes * Added is_opening * Added is_closing * Updated test based on changes * Formatting * Changed cover_state back to _state * Formatting and variable fixes * Test fixes * Formatting and variable touchup * Formatting * Optimizations * Add new cover features to demo * Add tests for demo cover closing/opening * Remove unused STATE_STOPPED * Add tests for new zwave cover values --- homeassistant/components/cover/__init__.py | 17 +++++++++- homeassistant/components/cover/demo.py | 38 ++++++++++++++++------ homeassistant/components/cover/zwave.py | 18 ++++++++-- homeassistant/const.py | 2 ++ tests/components/cover/test_demo.py | 8 +++++ tests/components/cover/test_zwave.py | 29 +++++++++++++---- 6 files changed, 91 insertions(+), 21 deletions(-) diff --git a/homeassistant/components/cover/__init__.py b/homeassistant/components/cover/__init__.py index df096c9ba80..23c0be1a43e 100644 --- a/homeassistant/components/cover/__init__.py +++ b/homeassistant/components/cover/__init__.py @@ -23,7 +23,7 @@ from homeassistant.const import ( SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER, SERVICE_SET_COVER_POSITION, SERVICE_STOP_COVER, SERVICE_OPEN_COVER_TILT, SERVICE_CLOSE_COVER_TILT, SERVICE_STOP_COVER_TILT, SERVICE_SET_COVER_TILT_POSITION, STATE_OPEN, - STATE_CLOSED, STATE_UNKNOWN, ATTR_ENTITY_ID) + STATE_CLOSED, STATE_UNKNOWN, STATE_OPENING, STATE_CLOSING, ATTR_ENTITY_ID) _LOGGER = logging.getLogger(__name__) @@ -225,6 +225,11 @@ class CoverDevice(Entity): @property def state(self): """Return the state of the cover.""" + if self.is_opening: + return STATE_OPENING + if self.is_closing: + return STATE_CLOSING + closed = self.is_closed if closed is None: @@ -262,6 +267,16 @@ class CoverDevice(Entity): return supported_features + @property + def is_opening(self): + """Return if the cover is opening or not.""" + pass + + @property + def is_closing(self): + """Return if the cover is closing or not.""" + pass + @property def is_closed(self): """Return if the cover is closed or not.""" diff --git a/homeassistant/components/cover/demo.py b/homeassistant/components/cover/demo.py index ed060659746..827b50c8af9 100644 --- a/homeassistant/components/cover/demo.py +++ b/homeassistant/components/cover/demo.py @@ -35,10 +35,12 @@ class DemoCover(CoverDevice): self._set_position = None self._set_tilt_position = None self._tilt_position = tilt_position - self._closing = True - self._closing_tilt = True + self._requested_closing = True + self._requested_closing_tilt = True self._unsub_listener_cover = None self._unsub_listener_cover_tilt = None + self._is_opening = False + self._is_closing = False if position is None: self._closed = True else: @@ -69,6 +71,16 @@ class DemoCover(CoverDevice): """Return if the cover is closed.""" return self._closed + @property + def is_closing(self): + """Return if the cover is closing.""" + return self._is_closing + + @property + def is_opening(self): + """Return if the cover is opening.""" + return self._is_opening + @property def device_class(self): """Return the class of this device, from component DEVICE_CLASSES.""" @@ -90,8 +102,10 @@ class DemoCover(CoverDevice): self.schedule_update_ha_state() return + self._is_closing = True self._listen_cover() - self._closing = True + self._requested_closing = True + self.schedule_update_ha_state() def close_cover_tilt(self, **kwargs): """Close the cover tilt.""" @@ -99,7 +113,7 @@ class DemoCover(CoverDevice): return self._listen_cover_tilt() - self._closing_tilt = True + self._requested_closing_tilt = True def open_cover(self, **kwargs): """Open the cover.""" @@ -110,8 +124,10 @@ class DemoCover(CoverDevice): self.schedule_update_ha_state() return + self._is_opening = True self._listen_cover() - self._closing = False + self._requested_closing = False + self.schedule_update_ha_state() def open_cover_tilt(self, **kwargs): """Open the cover tilt.""" @@ -119,7 +135,7 @@ class DemoCover(CoverDevice): return self._listen_cover_tilt() - self._closing_tilt = False + self._requested_closing_tilt = False def set_cover_position(self, position, **kwargs): """Move the cover to a specific position.""" @@ -128,7 +144,7 @@ class DemoCover(CoverDevice): return self._listen_cover() - self._closing = position < self._position + self._requested_closing = position < self._position def set_cover_tilt_position(self, tilt_position, **kwargs): """Move the cover til to a specific position.""" @@ -137,10 +153,12 @@ class DemoCover(CoverDevice): return self._listen_cover_tilt() - self._closing_tilt = tilt_position < self._tilt_position + self._requested_closing_tilt = tilt_position < self._tilt_position def stop_cover(self, **kwargs): """Stop the cover.""" + self._is_closing = False + self._is_opening = False if self._position is None: return if self._unsub_listener_cover is not None: @@ -166,7 +184,7 @@ class DemoCover(CoverDevice): def _time_changed_cover(self, now): """Track time changes.""" - if self._closing: + if self._requested_closing: self._position -= 10 else: self._position += 10 @@ -186,7 +204,7 @@ class DemoCover(CoverDevice): def _time_changed_cover_tilt(self, now): """Track time changes.""" - if self._closing_tilt: + if self._requested_closing_tilt: self._tilt_position -= 10 else: self._tilt_position += 10 diff --git a/homeassistant/components/cover/zwave.py b/homeassistant/components/cover/zwave.py index 6ec70d9a85a..b8daab81503 100644 --- a/homeassistant/components/cover/zwave.py +++ b/homeassistant/components/cover/zwave.py @@ -110,24 +110,36 @@ class ZwaveGarageDoor(zwave.ZWaveDeviceEntity, CoverDevice): def __init__(self, values): """Initialize the zwave garage door.""" ZWaveDeviceEntity.__init__(self, values, DOMAIN) + self._state = None self.update_properties() def update_properties(self): """Handle data changes for node values.""" self._state = self.values.primary.data + _LOGGER.debug("self._state=%s", self._state) + + @property + def is_opening(self): + """Return true if cover is in an opening state.""" + return self._state == "Opening" + + @property + def is_closing(self): + """Return true if cover is in an closing state.""" + return self._state == "Closing" @property def is_closed(self): """Return the current position of Zwave garage door.""" - return not self._state + return self._state == "Closed" def close_cover(self): """Close the garage door.""" - self.values.primary.data = False + self.values.primary.data = "Closed" def open_cover(self): """Open the garage door.""" - self.values.primary.data = True + self.values.primary.data = "Opened" @property def device_class(self): diff --git a/homeassistant/const.py b/homeassistant/const.py index b4b2aac52e3..ca8075b10ab 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -188,7 +188,9 @@ STATE_HOME = 'home' STATE_NOT_HOME = 'not_home' STATE_UNKNOWN = 'unknown' STATE_OPEN = 'open' +STATE_OPENING = 'opening' STATE_CLOSED = 'closed' +STATE_CLOSING = 'closing' STATE_PLAYING = 'playing' STATE_PAUSED = 'paused' STATE_IDLE = 'idle' diff --git a/tests/components/cover/test_demo.py b/tests/components/cover/test_demo.py index 83907de7708..9d26a6a4f4a 100644 --- a/tests/components/cover/test_demo.py +++ b/tests/components/cover/test_demo.py @@ -38,29 +38,37 @@ class TestCoverDemo(unittest.TestCase): def test_close_cover(self): """Test closing the cover.""" state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'open') self.assertEqual(70, state.attributes.get('current_position')) cover.close_cover(self.hass, ENTITY_COVER) self.hass.block_till_done() + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'closing') for _ in range(7): future = dt_util.utcnow() + timedelta(seconds=1) fire_time_changed(self.hass, future) self.hass.block_till_done() state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'closed') self.assertEqual(0, state.attributes.get('current_position')) def test_open_cover(self): """Test opening the cover.""" state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'open') self.assertEqual(70, state.attributes.get('current_position')) cover.open_cover(self.hass, ENTITY_COVER) self.hass.block_till_done() + state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'opening') for _ in range(7): future = dt_util.utcnow() + timedelta(seconds=1) fire_time_changed(self.hass, future) self.hass.block_till_done() state = self.hass.states.get(ENTITY_COVER) + self.assertEqual(state.state, 'open') self.assertEqual(100, state.attributes.get('current_position')) def test_set_cover_position(self): diff --git a/tests/components/cover/test_zwave.py b/tests/components/cover/test_zwave.py index e1ee6075cea..fe9abe7172c 100644 --- a/tests/components/cover/test_zwave.py +++ b/tests/components/cover/test_zwave.py @@ -161,31 +161,46 @@ def test_roller_reverse_open_close(hass, mock_openzwave): def test_garage_value_changed(hass, mock_openzwave): """Test position changed.""" node = MockNode() - value = MockValue(data=False, node=node, + value = MockValue(data="Closed", node=node, command_class=const.COMMAND_CLASS_BARRIER_OPERATOR) values = MockEntityValues(primary=value, node=node) device = zwave.get_device(hass=hass, node=node, values=values, node_config={}) assert device.is_closed + assert not device.is_opening + assert not device.is_closing - value.data = True + value.data = "Opening" value_changed(value) - assert not device.is_closed + assert device.is_opening + assert not device.is_closing + + value.data = "Opened" + value_changed(value) + assert not device.is_closed + assert not device.is_opening + assert not device.is_closing + + value.data = "Closing" + value_changed(value) + assert not device.is_closed + assert not device.is_opening + assert device.is_closing def test_garage_commands(hass, mock_openzwave): """Test position changed.""" node = MockNode() - value = MockValue(data=False, node=node, + value = MockValue(data="Closed", node=node, command_class=const.COMMAND_CLASS_BARRIER_OPERATOR) values = MockEntityValues(primary=value, node=node) device = zwave.get_device(hass=hass, node=node, values=values, node_config={}) - assert value.data is False + assert value.data == "Closed" device.open_cover() - assert value.data is True + assert value.data == "Opened" device.close_cover() - assert value.data is False + assert value.data == "Closed" From 0c97fe7eac0e5145fa7e9d3ac723ddb19433b2c8 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 28 Jul 2017 02:38:06 -0700 Subject: [PATCH 112/118] Version bump to 0.50 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index ca8075b10ab..751aa316084 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 50 -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) From 828c469ef7acc9e0c45d181cd07431c82b060aa4 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Fri, 28 Jul 2017 20:53:15 -0700 Subject: [PATCH 113/118] Fix Lint --- homeassistant/components/device_tracker/ubus.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/device_tracker/ubus.py b/homeassistant/components/device_tracker/ubus.py index cac4b7769e3..9ccc61dffc9 100644 --- a/homeassistant/components/device_tracker/ubus.py +++ b/homeassistant/components/device_tracker/ubus.py @@ -80,7 +80,7 @@ class UbusDeviceScanner(DeviceScanner): return self.last_results @_refresh_on_acccess_denied - def get_device_name(self, device): + def get_device_name(self, mac): """Return the name of the given device or None if we don't know.""" if self.leasefile is None: result = _req_json_rpc( @@ -105,10 +105,9 @@ class UbusDeviceScanner(DeviceScanner): # Error, handled in the _req_json_rpc return - return self.mac2name.get(device.upper(), None) + return self.mac2name.get(mac.upper(), None) @_refresh_on_acccess_denied - @Throttle(MIN_TIME_BETWEEN_SCANS) def _update_info(self): """Ensure the information from the Luci router is up to date. From 56f4486e0b86b6278f8853ed8741fab35bd77db0 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 29 Jul 2017 10:45:14 -0700 Subject: [PATCH 114/118] Update frontend --- homeassistant/components/frontend/version.py | 4 +- .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 139371 -> 139470 bytes .../www_static/home-assistant-polymer | 2 +- .../panels/ha-panel-shopping-list.html | 108 +++++++++++++++++- .../panels/ha-panel-shopping-list.html.gz | Bin 5308 -> 6144 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2490 -> 2491 bytes 8 files changed, 112 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index a0958f65d95..985177e95f3 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -3,7 +3,7 @@ FINGERPRINTS = { "compatibility.js": "8e4c44b5f4288cc48ec1ba94a9bec812", "core.js": "d4a7cb8c80c62b536764e0e81385f6aa", - "frontend.html": "c44e49b9a0d9b9e4a626b7af34ca97d0", + "frontend.html": "c544d43b2305b922e230c7c4e74d7613", "mdi.html": "e91f61a039ed0a9936e7ee5360da3870", "micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a", "panels/ha-panel-automation.html": "1982116c49ad26ee8d89295edc797084", @@ -19,6 +19,6 @@ FINGERPRINTS = { "panels/ha-panel-kiosk.html": "2ac2df41bd447600692a0054892fc094", "panels/ha-panel-logbook.html": "7c45bd41c146ec38b9938b8a5188bb0d", "panels/ha-panel-map.html": "50501cd53eb4304e9e46eb719aa894b7", - "panels/ha-panel-shopping-list.html": "c04af28c6475b90cbf2cf63ba1b841d0", + "panels/ha-panel-shopping-list.html": "0a6020ff6aec96a1e6220e00ea5b15f8", "panels/ha-panel-zwave.html": "422f95f820f8b6b231265351ffcf4dd1" } diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index ca86fd55d22..23c00301cf3 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -2,4 +2,4 @@ this._useContent&&u.Logical.saveChildNodes(this)},_setupRoot:function(){this._useContent&&(this._createLocalRoot(),this.dataHost||l(u.Logical.getChildNodes(this)))},_createLocalRoot:function(){this.shadyRoot=this.root,this.shadyRoot._distributionClean=!1,this.shadyRoot._hasDistributed=!1,this.shadyRoot._isShadyRoot=!0,this.shadyRoot._dirtyRoots=[];var e=this.shadyRoot._insertionPoints=!this._notes||this._notes._hasContent?this.shadyRoot.querySelectorAll("content"):[];u.Logical.saveChildNodes(this.shadyRoot);for(var t,o=0;o0?~setTimeout(e,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 +;return"matrix("+o(i[0])+" "+o(i[1])+" "+o(i[4])+" "+o(i[5])+" "+o(i[12])+" "+o(i[13])+")"}}(n),function(t,e){function i(t,e){e.concat([t]).forEach(function(e){e in document.documentElement.style&&(n[t]=e),r[e]=t})}var n={},r={};i("transform",["webkitTransform","msTransform"]),i("transformOrigin",["webkitTransformOrigin"]),i("perspective",["webkitPerspective"]),i("perspectiveOrigin",["webkitPerspectiveOrigin"]),t.propertyName=function(t){return n[t]||t},t.unprefixedPropertyName=function(t){return r[t]||t}}(n)}(),function(){if(void 0===document.createElement("div").animate([]).oncancel){var t;if(window.performance&&performance.now)var t=function(){return performance.now()};else var t=function(){return Date.now()};var e=function(t,e,i){this.target=t,this.currentTime=e,this.timelineTime=i,this.type="cancel",this.bubbles=!1,this.cancelable=!1,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)}}}(i),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){}}(0,r),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 a55204f203c36e36624813e501c97257c6755fd0..ad2cc4fb8cf0038f3583228f4f1371e0b31af173 100644 GIT binary patch delta 83077 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

n@8MrqIcGZWJUzG9?v980 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 JpTfb&003vCKdAr! diff --git a/homeassistant/components/frontend/www_static/home-assistant-polymer b/homeassistant/components/frontend/www_static/home-assistant-polymer index 19b903dfb7c..23f0744fe27 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 19b903dfb7c940bfafdecc5407526647d0aed2f2 +Subproject commit 23f0744fe272b6d306dde9592d872c34d53fa6b7 diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html index 20d85cfdee9..ea6e121dcf6 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html @@ -1 +1,107 @@ -

\ No newline at end of file + \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html.gz index 6c71d75c39096ba7237d6622b4046bb8c125c169..76577a763119ab74f445f4ec39294e974c418994 100644 GIT binary patch literal 6144 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 literal 5308 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 Date: Sat, 29 Jul 2017 08:48:09 -0700 Subject: [PATCH 115/118] Shopping List: edit name / complete status (#8666) * Shopping List: edit name / complete status * Change ID to be UUID based --- homeassistant/components/shopping_list.py | 72 ++++++++++++++++-- tests/components/test_shopping_list.py | 90 ++++++++++++++++++++++- 2 files changed, 154 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/shopping_list.py b/homeassistant/components/shopping_list.py index ac59c15572a..9922960da3f 100644 --- a/homeassistant/components/shopping_list.py +++ b/homeassistant/components/shopping_list.py @@ -1,9 +1,11 @@ """Component to manage a shoppling list.""" import asyncio import logging +import uuid import voluptuous as vol +from homeassistant.const import HTTP_NOT_FOUND, HTTP_BAD_REQUEST from homeassistant.core import callback from homeassistant.components import http from homeassistant.helpers import intent @@ -17,15 +19,20 @@ CONFIG_SCHEMA = vol.Schema({DOMAIN: {}}, extra=vol.ALLOW_EXTRA) EVENT = 'shopping_list_updated' INTENT_ADD_ITEM = 'HassShoppingListAddItem' INTENT_LAST_ITEMS = 'HassShoppingListLastItems' +ITEM_UPDATE_SCHEMA = vol.Schema({ + 'complete': bool, + 'name': str, +}) @asyncio.coroutine def async_setup(hass, config): """Initialize the shopping list.""" - hass.data[DOMAIN] = [] + hass.data[DOMAIN] = ShoppingData([]) intent.async_register(hass, AddItemIntent()) intent.async_register(hass, ListTopItemsIntent()) hass.http.register_view(ShoppingListView) + hass.http.register_view(UpdateShoppingListItemView) hass.components.conversation.async_register(INTENT_ADD_ITEM, [ 'Add {item} to my shopping list', ]) @@ -37,6 +44,37 @@ def async_setup(hass, config): return True +class ShoppingData: + """Class to hold shopping list data.""" + + def __init__(self, items): + """Initialize the shopping list.""" + self.items = items + + def add(self, name): + """Add a shopping list item.""" + self.items.append({ + 'name': name, + 'id': uuid.uuid4().hex, + 'complete': False + }) + + def update(self, item_id, info): + """Update a shopping list item.""" + item = next((itm for itm in self.items if itm['id'] == item_id), None) + + if item is None: + raise KeyError + + info = ITEM_UPDATE_SCHEMA(info) + item.update(info) + return item + + def clear_completed(self): + """Clear completed items.""" + self.items = [itm for itm in self.items if not itm['complete']] + + class AddItemIntent(intent.IntentHandler): """Handle AddItem intents.""" @@ -50,7 +88,7 @@ class AddItemIntent(intent.IntentHandler): """Handle the intent.""" slots = self.async_validate_slots(intent_obj.slots) item = slots['item']['value'] - intent_obj.hass.data[DOMAIN].append(item) + intent_obj.hass.data[DOMAIN].add(item) response = intent_obj.create_response() response.async_set_speech( @@ -70,16 +108,17 @@ class ListTopItemsIntent(intent.IntentHandler): @asyncio.coroutine def async_handle(self, intent_obj): """Handle the intent.""" - items = intent_obj.hass.data[DOMAIN][-5:] + items = intent_obj.hass.data[DOMAIN].items[-5:] response = intent_obj.create_response() - if len(items) == 0: + if not items: response.async_set_speech( "There are no items on your shopping list") else: response.async_set_speech( "These are the top {} items on your shopping list: {}".format( - min(len(items), 5), ', '.join(reversed(items)))) + min(len(items), 5), + ', '.join(itm['name'] for itm in reversed(items)))) return response @@ -92,4 +131,25 @@ class ShoppingListView(http.HomeAssistantView): @callback def get(self, request): """Retrieve if API is running.""" - return self.json(request.app['hass'].data[DOMAIN]) + return self.json(request.app['hass'].data[DOMAIN].items) + + +class UpdateShoppingListItemView(http.HomeAssistantView): + """View to retrieve shopping list content.""" + + url = '/api/shopping_list/{item_id}' + name = "api:shopping_list:id" + + @callback + def post(self, request, item_id): + """Retrieve if API is running.""" + data = yield from request.json() + + try: + item = request.app['hass'].data[DOMAIN].update(item_id, data) + request.app['hass'].bus.async_fire(EVENT) + return self.json(item) + except KeyError: + return self.json_message('Item not found', HTTP_NOT_FOUND) + except vol.Invalid: + return self.json_message('Item not found', HTTP_BAD_REQUEST) diff --git a/tests/components/test_shopping_list.py b/tests/components/test_shopping_list.py index c25ce593c54..e4a99ad39d4 100644 --- a/tests/components/test_shopping_list.py +++ b/tests/components/test_shopping_list.py @@ -42,7 +42,7 @@ def test_recent_items_intent(hass): @asyncio.coroutine -def test_api(hass, test_client): +def test_api_get_all(hass, test_client): """Test the API.""" yield from async_setup_component(hass, 'shopping_list', {}) @@ -58,4 +58,90 @@ def test_api(hass, test_client): assert resp.status == 200 data = yield from resp.json() - assert data == ['beer', 'wine'] + assert len(data) == 2 + assert data[0]['name'] == 'beer' + assert not data[0]['complete'] + assert data[1]['name'] == 'wine' + assert not data[1]['complete'] + + +@asyncio.coroutine +def test_api_update(hass, test_client): + """Test the API.""" + yield from async_setup_component(hass, 'shopping_list', {}) + + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'beer'}} + ) + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'wine'}} + ) + + beer_id = hass.data['shopping_list'].items[0]['id'] + wine_id = hass.data['shopping_list'].items[1]['id'] + + client = yield from test_client(hass.http.app) + resp = yield from client.post( + '/api/shopping_list/{}'.format(beer_id), json={ + 'name': 'soda' + }) + + assert resp.status == 200 + data = yield from resp.json() + assert data == { + 'id': beer_id, + 'name': 'soda', + 'complete': False + } + + resp = yield from client.post( + '/api/shopping_list/{}'.format(wine_id), json={ + 'complete': True + }) + + assert resp.status == 200 + data = yield from resp.json() + assert data == { + 'id': wine_id, + 'name': 'wine', + 'complete': True + } + + beer, wine = hass.data['shopping_list'].items + assert beer == { + 'id': beer_id, + 'name': 'soda', + 'complete': False + } + assert wine == { + 'id': wine_id, + 'name': 'wine', + 'complete': True + } + + +@asyncio.coroutine +def test_api_update_fails(hass, test_client): + """Test the API.""" + yield from async_setup_component(hass, 'shopping_list', {}) + + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'beer'}} + ) + + client = yield from test_client(hass.http.app) + resp = yield from client.post( + '/api/shopping_list/non_existing', json={ + 'name': 'soda' + }) + + assert resp.status == 404 + + beer_id = hass.data['shopping_list'].items[0]['id'] + client = yield from test_client(hass.http.app) + resp = yield from client.post( + '/api/shopping_list/{}'.format(beer_id), json={ + 'name': 123, + }) + + assert resp.status == 400 From c376bc2e451734d03f559a5743a9020c105992be Mon Sep 17 00:00:00 2001 From: William Scanlon Date: Fri, 28 Jul 2017 12:02:16 -0400 Subject: [PATCH 116/118] Support for Wink local control (#8607) * Support for Wink local control --- homeassistant/components/wink.py | 38 ++++++++++++++++++++++---------- requirements_all.txt | 2 +- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/wink.py b/homeassistant/components/wink.py index 1783d4bd79a..e6d60aa5568 100644 --- a/homeassistant/components/wink.py +++ b/homeassistant/components/wink.py @@ -25,7 +25,7 @@ from homeassistant.const import ( from homeassistant.helpers.entity import Entity import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['python-wink==1.3.1', 'pubnubsub-handler==1.0.2'] +REQUIREMENTS = ['python-wink==1.4.2', 'pubnubsub-handler==1.0.2'] _LOGGER = logging.getLogger(__name__) @@ -36,10 +36,10 @@ SUBSCRIPTION_HANDLER = None CONF_CLIENT_ID = 'client_id' CONF_CLIENT_SECRET = 'client_secret' CONF_USER_AGENT = 'user_agent' -CONF_OATH = 'oath' +CONF_OAUTH = 'oauth' +CONF_LOCAL_CONTROL = 'local_control' CONF_APPSPOT = 'appspot' -CONF_DEFINED_BOTH_MSG = 'Remove access token to use oath2.' -CONF_MISSING_OATH_MSG = 'Missing oath2 credentials.' +CONF_MISSING_OAUTH_MSG = 'Missing oauth2 credentials.' CONF_TOKEN_URL = "https://winkbearertoken.appspot.com/token" ATTR_ACCESS_TOKEN = 'access_token' @@ -64,15 +64,14 @@ SERVICE_KEEP_ALIVE = 'keep_pubnub_updates_flowing' CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Inclusive(CONF_EMAIL, CONF_APPSPOT, - msg=CONF_MISSING_OATH_MSG): cv.string, + msg=CONF_MISSING_OAUTH_MSG): cv.string, vol.Inclusive(CONF_PASSWORD, CONF_APPSPOT, - msg=CONF_MISSING_OATH_MSG): cv.string, - vol.Inclusive(CONF_CLIENT_ID, CONF_OATH, - msg=CONF_MISSING_OATH_MSG): cv.string, - vol.Inclusive(CONF_CLIENT_SECRET, CONF_OATH, - msg=CONF_MISSING_OATH_MSG): cv.string, - vol.Exclusive(CONF_EMAIL, CONF_OATH, - msg=CONF_DEFINED_BOTH_MSG): cv.string, + msg=CONF_MISSING_OAUTH_MSG): cv.string, + vol.Inclusive(CONF_CLIENT_ID, CONF_OAUTH, + msg=CONF_MISSING_OAUTH_MSG): cv.string, + vol.Inclusive(CONF_CLIENT_SECRET, CONF_OAUTH, + msg=CONF_MISSING_OAUTH_MSG): cv.string, + vol.Optional(CONF_LOCAL_CONTROL, default=False): cv.boolean }) }, extra=vol.ALLOW_EXTRA) @@ -206,8 +205,11 @@ def setup(hass, config): client_secret = config[DOMAIN].get(ATTR_CLIENT_SECRET) email = config[DOMAIN].get(CONF_EMAIL) password = config[DOMAIN].get(CONF_PASSWORD) + local_control = config[DOMAIN].get(CONF_LOCAL_CONTROL) if None not in [client_id, client_secret]: _LOGGER.info("Using legacy oauth authentication") + if not local_control: + pywink.disable_local_control() hass.data[DOMAIN]["oauth"]["client_id"] = client_id hass.data[DOMAIN]["oauth"]["client_secret"] = client_secret hass.data[DOMAIN]["oauth"]["email"] = email @@ -216,11 +218,14 @@ def setup(hass, config): client_id, client_secret) elif None not in [email, password]: _LOGGER.info("Using web form authentication") + pywink.disable_local_control() hass.data[DOMAIN]["oauth"]["email"] = email hass.data[DOMAIN]["oauth"]["password"] = password _get_wink_token_from_web() else: _LOGGER.info("Using new oauth authentication") + if not local_control: + pywink.disable_local_control() config_path = hass.config.path(WINK_CONFIG_FILE) if os.path.isfile(config_path): config_file = _read_config_file(config_path) @@ -304,6 +309,15 @@ def setup(hass, config): hass.bus.listen(EVENT_HOMEASSISTANT_STOP, stop_subscription) + def save_credentials(event): + """Save currently set oauth credentials.""" + if hass.data[DOMAIN]["oauth"].get("email") is None: + config_path = hass.config.path(WINK_CONFIG_FILE) + _config = pywink.get_current_oauth_credentials() + _write_config_file(config_path, _config) + + hass.bus.listen(EVENT_HOMEASSISTANT_STOP, save_credentials) + def force_update(call): """Force all devices to poll the Wink API.""" _LOGGER.info("Refreshing Wink states from API") diff --git a/requirements_all.txt b/requirements_all.txt index 5bce15dbfd2..84e3618d2a0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -768,7 +768,7 @@ python-velbus==2.0.11 python-vlc==1.1.2 # homeassistant.components.wink -python-wink==1.3.1 +python-wink==1.4.2 # homeassistant.components.zwave python_openzwave==0.4.0.31 From 12dec93565a1bea09876d6cb9a429be7968f3599 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 29 Jul 2017 12:18:50 -0700 Subject: [PATCH 117/118] Update frontend --- homeassistant/components/frontend/version.py | 4 ++-- .../frontend/www_static/frontend.html | 2 +- .../frontend/www_static/frontend.html.gz | Bin 139470 -> 139501 bytes .../www_static/home-assistant-polymer | 2 +- .../panels/ha-panel-shopping-list.html | 10 +++++++--- .../panels/ha-panel-shopping-list.html.gz | Bin 6144 -> 15408 bytes .../frontend/www_static/service_worker.js | 2 +- .../frontend/www_static/service_worker.js.gz | Bin 2491 -> 2492 bytes 8 files changed, 12 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/frontend/version.py b/homeassistant/components/frontend/version.py index 985177e95f3..469452f7e49 100644 --- a/homeassistant/components/frontend/version.py +++ b/homeassistant/components/frontend/version.py @@ -3,7 +3,7 @@ FINGERPRINTS = { "compatibility.js": "8e4c44b5f4288cc48ec1ba94a9bec812", "core.js": "d4a7cb8c80c62b536764e0e81385f6aa", - "frontend.html": "c544d43b2305b922e230c7c4e74d7613", + "frontend.html": "7d599996578579600f1000d6d25e649d", "mdi.html": "e91f61a039ed0a9936e7ee5360da3870", "micromarkdown-js.html": "93b5ec4016f0bba585521cf4d18dec1a", "panels/ha-panel-automation.html": "1982116c49ad26ee8d89295edc797084", @@ -19,6 +19,6 @@ FINGERPRINTS = { "panels/ha-panel-kiosk.html": "2ac2df41bd447600692a0054892fc094", "panels/ha-panel-logbook.html": "7c45bd41c146ec38b9938b8a5188bb0d", "panels/ha-panel-map.html": "50501cd53eb4304e9e46eb719aa894b7", - "panels/ha-panel-shopping-list.html": "0a6020ff6aec96a1e6220e00ea5b15f8", + "panels/ha-panel-shopping-list.html": "1d7126efc9ff9a102df7465d803a11d1", "panels/ha-panel-zwave.html": "422f95f820f8b6b231265351ffcf4dd1" } diff --git a/homeassistant/components/frontend/www_static/frontend.html b/homeassistant/components/frontend/www_static/frontend.html index 23c00301cf3..7dd7b17c987 100644 --- a/homeassistant/components/frontend/www_static/frontend.html +++ b/homeassistant/components/frontend/www_static/frontend.html @@ -2,4 +2,4 @@ this._useContent&&u.Logical.saveChildNodes(this)},_setupRoot:function(){this._useContent&&(this._createLocalRoot(),this.dataHost||l(u.Logical.getChildNodes(this)))},_createLocalRoot:function(){this.shadyRoot=this.root,this.shadyRoot._distributionClean=!1,this.shadyRoot._hasDistributed=!1,this.shadyRoot._isShadyRoot=!0,this.shadyRoot._dirtyRoots=[];var e=this.shadyRoot._insertionPoints=!this._notes||this._notes._hasContent?this.shadyRoot.querySelectorAll("content"):[];u.Logical.saveChildNodes(this.shadyRoot);for(var t,o=0;o0?~setTimeout(e,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 +;return"matrix("+o(i[0])+" "+o(i[1])+" "+o(i[4])+" "+o(i[5])+" "+o(i[12])+" "+o(i[13])+")"}}(n),function(t,e){function i(t,e){e.concat([t]).forEach(function(e){e in document.documentElement.style&&(n[t]=e),r[e]=t})}var n={},r={};i("transform",["webkitTransform","msTransform"]),i("transformOrigin",["webkitTransformOrigin"]),i("perspective",["webkitPerspective"]),i("perspectiveOrigin",["webkitPerspectiveOrigin"]),t.propertyName=function(t){return n[t]||t},t.unprefixedPropertyName=function(t){return r[t]||t}}(n)}(),function(){if(void 0===document.createElement("div").animate([]).oncancel){var t;if(window.performance&&performance.now)var t=function(){return performance.now()};else var t=function(){return Date.now()};var e=function(t,e,i){this.target=t,this.currentTime=e,this.timelineTime=i,this.type="cancel",this.bubbles=!1,this.cancelable=!1,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)}}}(i),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){}}(0,r),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 ad2cc4fb8cf0038f3583228f4f1371e0b31af173..d41c459ae9b59c2f9233602083606c4a653c80d6 100644 GIT binary patch delta 27986 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 bU7@1ru$nu?t}({u&ws`+b=$8Y(>WLbHJ+EP delta 27999 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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 23f0744fe27..7f6aeaf2a2e 160000 --- a/homeassistant/components/frontend/www_static/home-assistant-polymer +++ b/homeassistant/components/frontend/www_static/home-assistant-polymer @@ -1 +1 @@ -Subproject commit 23f0744fe272b6d306dde9592d872c34d53fa6b7 +Subproject commit 7f6aeaf2a2e8a91f59030300fbf47f0b8e3952f1 diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html index ea6e121dcf6..0eb37f1a00d 100644 --- a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html +++ b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html.gz b/homeassistant/components/frontend/www_static/panels/ha-panel-shopping-list.html.gz index 76577a763119ab74f445f4ec39294e974c418994..687f39056836d14629c45edd06169259406744f6 100644 GIT binary patch literal 15408 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 z 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%0Du!jDY`Z(MPk;8Gk4!7 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 p9&eY|Jx$hRSH~D? literal 6144 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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 05af75abb23..173132fd3a9 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=[["/","a8feb2ef5f35df9e3b9829f83e1de98c"],["/frontend/panels/dev-event-77784d5f0c73fcc3b29b6cc050bdf324.html","eebf53a12ae770fea7c5429de2db810c"],["/frontend/panels/dev-info-24e888ec7a8acd0c395b34396e9001bc.html","7bb116813e8dbab7bcfabdf4de3ec83f"],["/frontend/panels/dev-service-86a42a17f4894478b6b77bc636beafd0.html","86888ff94a1958074cde156739687ba0"],["/frontend/panels/dev-state-31ef6ffe3347cdda5bb0cbbc54b62cde.html","38dc27f1f817045900f396a61c7e736f"],["/frontend/panels/dev-template-d1d76e20fe9622cddee33e67318abde8.html","2973bd8b33775239a4a05d6d569dd331"],["/frontend/panels/map-50501cd53eb4304e9e46eb719aa894b7.html","410d870df0226d08078d8dc45d02a8ef"],["/static/compatibility-8e4c44b5f4288cc48ec1ba94a9bec812.js","4704a985ad259e324c3d8a0a40f6d937"],["/static/core-d4a7cb8c80c62b536764e0e81385f6aa.js","37e34ec6aa0fa155c7d50e2883be1ead"],["/static/frontend-c544d43b2305b922e230c7c4e74d7613.html","54241a208f8a65b56444646c137feaef"],["/static/mdi-e91f61a039ed0a9936e7ee5360da3870.html","5e587bc82719b740a4f0798722a83aee"],["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","32b5a9b7ada86304bec6b43d3f2194f0"]],cacheName="sw-precache-v3--"+(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()},cleanResponse=function(e){return e.redirected?("body"in e?Promise.resolve(e.body):e.blob()).then(function(t){return new Response(t,{headers:e.headers,status:e.status,statusText:e.statusText})}):Promise.resolve(e)},createCacheKey=function(e,t,a,n){var c=new URL(e);return n&&c.pathname.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)){var n=new Request(a,{credentials:"same-origin"});return fetch(n).then(function(t){if(!t.ok)throw new Error("Request for "+a+" returned a response with status "+t.status);return cleanResponse(t).then(function(t){return e.put(a,t)})})}}))})}).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);t||(a=addDirectoryIndex(a,"index.html"),t=urlsToCacheKeys.has(a));!t&&"navigate"===e.request.mode&&isPathWhitelisted(["^((?!(static|api|local|service_worker.js|manifest.json)).)*$"],e.request.url)&&(a=new URL("/",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)&&e.waitUntil(clients.matchAll({type:"window"}).then(function(e){var a,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 From a760673ad66537df0b42ca0c408e88d39338b399 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 29 Jul 2017 12:22:38 -0700 Subject: [PATCH 118/118] Persist shopping list + clear completed (#8697) --- homeassistant/components/shopping_list.py | 71 +++++++++++++++++++---- tests/components/test_shopping_list.py | 53 ++++++++++++++++- 2 files changed, 111 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/shopping_list.py b/homeassistant/components/shopping_list.py index 9922960da3f..ad9fae67bc6 100644 --- a/homeassistant/components/shopping_list.py +++ b/homeassistant/components/shopping_list.py @@ -1,6 +1,8 @@ """Component to manage a shoppling list.""" import asyncio +import json import logging +import os import uuid import voluptuous as vol @@ -23,43 +25,55 @@ ITEM_UPDATE_SCHEMA = vol.Schema({ 'complete': bool, 'name': str, }) +PERSISTENCE = '.shopping_list.json' @asyncio.coroutine def async_setup(hass, config): """Initialize the shopping list.""" - hass.data[DOMAIN] = ShoppingData([]) + data = hass.data[DOMAIN] = ShoppingData(hass) + yield from data.async_load() + intent.async_register(hass, AddItemIntent()) intent.async_register(hass, ListTopItemsIntent()) + hass.http.register_view(ShoppingListView) hass.http.register_view(UpdateShoppingListItemView) + hass.http.register_view(ClearCompletedItemsView) + hass.components.conversation.async_register(INTENT_ADD_ITEM, [ 'Add {item} to my shopping list', ]) hass.components.conversation.async_register(INTENT_LAST_ITEMS, [ 'What is on my shopping list' ]) + hass.components.frontend.register_built_in_panel( 'shopping-list', 'Shopping List', 'mdi:cart') + return True class ShoppingData: """Class to hold shopping list data.""" - def __init__(self, items): + def __init__(self, hass): """Initialize the shopping list.""" - self.items = items + self.hass = hass + self.items = [] - def add(self, name): + @callback + def async_add(self, name): """Add a shopping list item.""" self.items.append({ 'name': name, 'id': uuid.uuid4().hex, 'complete': False }) + self.hass.async_add_job(self.save) - def update(self, item_id, info): + @callback + def async_update(self, item_id, info): """Update a shopping list item.""" item = next((itm for itm in self.items if itm['id'] == item_id), None) @@ -68,11 +82,33 @@ class ShoppingData: info = ITEM_UPDATE_SCHEMA(info) item.update(info) + self.hass.async_add_job(self.save) return item - def clear_completed(self): + @callback + def async_clear_completed(self): """Clear completed items.""" self.items = [itm for itm in self.items if not itm['complete']] + self.hass.async_add_job(self.save) + + @asyncio.coroutine + def async_load(self): + """Load items.""" + def load(): + """Load the items synchronously.""" + path = self.hass.config.path(PERSISTENCE) + if not os.path.isfile(path): + return [] + with open(path) as file: + return json.loads(file.read()) + + items = yield from self.hass.async_add_job(load) + self.items = items + + def save(self): + """Save the items.""" + with open(self.hass.config.path(PERSISTENCE), 'wt') as file: + file.write(json.dumps(self.items, sort_keys=True, indent=4)) class AddItemIntent(intent.IntentHandler): @@ -88,7 +124,7 @@ class AddItemIntent(intent.IntentHandler): """Handle the intent.""" slots = self.async_validate_slots(intent_obj.slots) item = slots['item']['value'] - intent_obj.hass.data[DOMAIN].add(item) + intent_obj.hass.data[DOMAIN].async_add(item) response = intent_obj.create_response() response.async_set_speech( @@ -137,8 +173,8 @@ class ShoppingListView(http.HomeAssistantView): class UpdateShoppingListItemView(http.HomeAssistantView): """View to retrieve shopping list content.""" - url = '/api/shopping_list/{item_id}' - name = "api:shopping_list:id" + url = '/api/shopping_list/item/{item_id}' + name = "api:shopping_list:item:id" @callback def post(self, request, item_id): @@ -146,10 +182,25 @@ class UpdateShoppingListItemView(http.HomeAssistantView): data = yield from request.json() try: - item = request.app['hass'].data[DOMAIN].update(item_id, data) + item = request.app['hass'].data[DOMAIN].async_update(item_id, data) request.app['hass'].bus.async_fire(EVENT) return self.json(item) except KeyError: return self.json_message('Item not found', HTTP_NOT_FOUND) except vol.Invalid: return self.json_message('Item not found', HTTP_BAD_REQUEST) + + +class ClearCompletedItemsView(http.HomeAssistantView): + """View to retrieve shopping list content.""" + + url = '/api/shopping_list/clear_completed' + name = "api:shopping_list:clear_completed" + + @callback + def post(self, request): + """Retrieve if API is running.""" + hass = request.app['hass'] + hass.data[DOMAIN].async_clear_completed() + hass.bus.async_fire(EVENT) + return self.json_message('Cleared completed items.') diff --git a/tests/components/test_shopping_list.py b/tests/components/test_shopping_list.py index e4a99ad39d4..449eab65016 100644 --- a/tests/components/test_shopping_list.py +++ b/tests/components/test_shopping_list.py @@ -1,10 +1,20 @@ """Test shopping list component.""" import asyncio +from unittest.mock import patch + +import pytest from homeassistant.bootstrap import async_setup_component from homeassistant.helpers import intent +@pytest.fixture(autouse=True) +def mock_shopping_list_save(): + """Stub out the persistence.""" + with patch('homeassistant.components.shopping_list.ShoppingData.save'): + yield + + @asyncio.coroutine def test_add_item(hass): """Test adding an item intent.""" @@ -82,7 +92,7 @@ def test_api_update(hass, test_client): client = yield from test_client(hass.http.app) resp = yield from client.post( - '/api/shopping_list/{}'.format(beer_id), json={ + '/api/shopping_list/item/{}'.format(beer_id), json={ 'name': 'soda' }) @@ -95,7 +105,7 @@ def test_api_update(hass, test_client): } resp = yield from client.post( - '/api/shopping_list/{}'.format(wine_id), json={ + '/api/shopping_list/item/{}'.format(wine_id), json={ 'complete': True }) @@ -140,8 +150,45 @@ def test_api_update_fails(hass, test_client): beer_id = hass.data['shopping_list'].items[0]['id'] client = yield from test_client(hass.http.app) resp = yield from client.post( - '/api/shopping_list/{}'.format(beer_id), json={ + '/api/shopping_list/item/{}'.format(beer_id), json={ 'name': 123, }) assert resp.status == 400 + + +@asyncio.coroutine +def test_api_clear_completed(hass, test_client): + """Test the API.""" + yield from async_setup_component(hass, 'shopping_list', {}) + + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'beer'}} + ) + yield from intent.async_handle( + hass, 'test', 'HassShoppingListAddItem', {'item': {'value': 'wine'}} + ) + + beer_id = hass.data['shopping_list'].items[0]['id'] + wine_id = hass.data['shopping_list'].items[1]['id'] + + client = yield from test_client(hass.http.app) + + # Mark beer as completed + resp = yield from client.post( + '/api/shopping_list/item/{}'.format(beer_id), json={ + 'complete': True + }) + assert resp.status == 200 + + resp = yield from client.post('/api/shopping_list/clear_completed') + assert resp.status == 200 + + items = hass.data['shopping_list'].items + assert len(items) == 1 + + assert items[0] == { + 'id': wine_id, + 'name': 'wine', + 'complete': False + }