mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 16:27:08 +00:00
Bootstrap / Component setup async (#6264)
* Bootstrap / Entiy setup async * Cleanup add_job stuff / return task/future object * Address paulus comments / part 1 * fix install pip * Cleanup bootstrap / move config stuff to config.py * Make demo async * Further bootstrap improvement * Address Martin's comments * Fix initial tests * Fix final tests * Fix bug with prepare loader * Remove no longer needed things * Log error when invalid config * More cleanup * Cleanups platform events & fix lint * Use a non blocking add_entities callback for platform * Fix Autoamtion is setup befor entity is ready * Better automation fix * Address paulus comments * Typo * fix lint * rename functions * fix tests * fix test * change exceptions * fix spell
This commit is contained in:
parent
383b0914b3
commit
41f558b181
@ -4,38 +4,41 @@ import logging
|
|||||||
import logging.handlers
|
import logging.handlers
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from time import time
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Any, Optional, Dict
|
from typing import Any, Optional, Dict
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from voluptuous.humanize import humanize_error
|
|
||||||
|
|
||||||
import homeassistant.components as core_components
|
import homeassistant.components as core_components
|
||||||
from homeassistant.components import persistent_notification
|
from homeassistant.components import persistent_notification
|
||||||
import homeassistant.config as conf_util
|
import homeassistant.config as conf_util
|
||||||
|
from homeassistant.config import async_notify_setup_error
|
||||||
import homeassistant.core as core
|
import homeassistant.core as core
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE
|
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE
|
||||||
import homeassistant.loader as loader
|
import homeassistant.loader as loader
|
||||||
import homeassistant.util.package as pkg_util
|
import homeassistant.util.package as pkg_util
|
||||||
from homeassistant.util.async import (
|
from homeassistant.util.async import run_coroutine_threadsafe
|
||||||
run_coroutine_threadsafe, run_callback_threadsafe)
|
|
||||||
from homeassistant.util.logging import AsyncHandler
|
from homeassistant.util.logging import AsyncHandler
|
||||||
from homeassistant.util.yaml import clear_secret_cache
|
from homeassistant.util.yaml import clear_secret_cache
|
||||||
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
|
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import event_decorators, service
|
||||||
event_decorators, service, config_per_platform, extract_domain_configs)
|
|
||||||
from homeassistant.helpers.signal import async_register_signal_handling
|
from homeassistant.helpers.signal import async_register_signal_handling
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
ATTR_COMPONENT = 'component'
|
ATTR_COMPONENT = 'component'
|
||||||
|
|
||||||
|
DATA_SETUP = 'setup_tasks'
|
||||||
|
DATA_PIP_LOCK = 'pip_lock'
|
||||||
|
|
||||||
ERROR_LOG_FILENAME = 'home-assistant.log'
|
ERROR_LOG_FILENAME = 'home-assistant.log'
|
||||||
DATA_PERSISTENT_ERRORS = 'bootstrap_persistent_errors'
|
|
||||||
HA_COMPONENT_URL = '[{}](https://home-assistant.io/components/{}/)'
|
FIRST_INIT_COMPONENT = set((
|
||||||
|
'recorder', 'mqtt', 'mqtt_eventstream', 'logger', 'introduction'))
|
||||||
|
|
||||||
|
|
||||||
def setup_component(hass: core.HomeAssistant, domain: str,
|
def setup_component(hass: core.HomeAssistant, domain: str,
|
||||||
@ -52,94 +55,131 @@ def async_setup_component(hass: core.HomeAssistant, domain: str,
|
|||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
if domain in hass.config.components:
|
setup_tasks = hass.data.get(DATA_SETUP)
|
||||||
_LOGGER.debug('Component %s already set up.', domain)
|
|
||||||
return True
|
|
||||||
|
|
||||||
if not loader.PREPARED:
|
if setup_tasks is not None and domain in setup_tasks:
|
||||||
yield from hass.loop.run_in_executor(None, loader.prepare, hass)
|
return (yield from setup_tasks[domain])
|
||||||
|
|
||||||
if config is None:
|
if config is None:
|
||||||
config = {}
|
config = {}
|
||||||
|
|
||||||
components = loader.load_order_component(domain)
|
if setup_tasks is None:
|
||||||
|
setup_tasks = hass.data[DATA_SETUP] = {}
|
||||||
|
|
||||||
# OrderedSet is empty if component or dependencies could not be resolved
|
task = setup_tasks[domain] = hass.async_add_job(
|
||||||
if not components:
|
_async_setup_component(hass, domain, config))
|
||||||
_async_persistent_notification(hass, domain, True)
|
|
||||||
return False
|
|
||||||
|
|
||||||
for component in components:
|
return (yield from task)
|
||||||
res = yield from _async_setup_component(hass, component, config)
|
|
||||||
if not res:
|
|
||||||
_LOGGER.error('Component %s failed to setup', component)
|
|
||||||
_async_persistent_notification(hass, component, True)
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _handle_requirements(hass: core.HomeAssistant, component,
|
@asyncio.coroutine
|
||||||
name: str) -> bool:
|
def _async_process_requirements(hass: core.HomeAssistant, name: str,
|
||||||
|
requirements) -> bool:
|
||||||
"""Install the requirements for a component.
|
"""Install the requirements for a component.
|
||||||
|
|
||||||
This method needs to run in an executor.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
if hass.config.skip_pip or not hasattr(component, 'REQUIREMENTS'):
|
if hass.config.skip_pip:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
for req in component.REQUIREMENTS:
|
pip_lock = hass.data.get(DATA_PIP_LOCK)
|
||||||
if not pkg_util.install_package(req, target=hass.config.path('deps')):
|
if pip_lock is None:
|
||||||
|
pip_lock = hass.data[DATA_PIP_LOCK] = asyncio.Lock(loop=hass.loop)
|
||||||
|
|
||||||
|
def pip_install(mod):
|
||||||
|
"""Install packages."""
|
||||||
|
return pkg_util.install_package(mod, target=hass.config.path('deps'))
|
||||||
|
|
||||||
|
with (yield from pip_lock):
|
||||||
|
for req in requirements:
|
||||||
|
ret = yield from hass.loop.run_in_executor(None, pip_install, req)
|
||||||
|
if not ret:
|
||||||
_LOGGER.error('Not initializing %s because could not install '
|
_LOGGER.error('Not initializing %s because could not install '
|
||||||
'dependency %s', name, req)
|
'dependency %s', name, req)
|
||||||
_async_persistent_notification(hass, name)
|
async_notify_setup_error(hass, name)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def _async_process_dependencies(hass, config, name, dependencies):
|
||||||
|
"""Ensure all dependencies are set up."""
|
||||||
|
blacklisted = [dep for dep in dependencies
|
||||||
|
if dep in loader.DEPENDENCY_BLACKLIST]
|
||||||
|
|
||||||
|
if blacklisted:
|
||||||
|
_LOGGER.error('Unable to setup dependencies of %s: '
|
||||||
|
'found blacklisted dependencies: %s',
|
||||||
|
name, ', '.join(blacklisted))
|
||||||
|
return False
|
||||||
|
|
||||||
|
tasks = [async_setup_component(hass, dep, config) for dep
|
||||||
|
in dependencies]
|
||||||
|
|
||||||
|
if not tasks:
|
||||||
|
return True
|
||||||
|
|
||||||
|
results = yield from asyncio.gather(*tasks, loop=hass.loop)
|
||||||
|
|
||||||
|
failed = [dependencies[idx] for idx, res
|
||||||
|
in enumerate(results) if not res]
|
||||||
|
|
||||||
|
if failed:
|
||||||
|
_LOGGER.error('Unable to setup dependencies of %s. '
|
||||||
|
'Setup failed for dependencies: %s',
|
||||||
|
name, ', '.join(failed))
|
||||||
|
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _async_setup_component(hass: core.HomeAssistant,
|
def _async_setup_component(hass: core.HomeAssistant,
|
||||||
domain: str, config) -> bool:
|
domain: str, config) -> bool:
|
||||||
"""Setup a component for Home Assistant.
|
"""Setup a component for Home Assistant.
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
|
|
||||||
|
hass: Home Assistant instance.
|
||||||
|
domain: Domain of component to setup.
|
||||||
|
config: The Home Assistant configuration.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-return-statements
|
def log_error(msg):
|
||||||
if domain in hass.config.components:
|
"""Log helper."""
|
||||||
return True
|
_LOGGER.error('Setup failed for %s: %s', domain, msg)
|
||||||
|
async_notify_setup_error(hass, domain, True)
|
||||||
|
|
||||||
setup_lock = hass.data.get('setup_lock')
|
# Validate no circular dependencies
|
||||||
if setup_lock is None:
|
components = loader.load_order_component(domain)
|
||||||
setup_lock = hass.data['setup_lock'] = asyncio.Lock(loop=hass.loop)
|
|
||||||
|
|
||||||
setup_progress = hass.data.get('setup_progress')
|
# OrderedSet is empty if component or dependencies could not be resolved
|
||||||
if setup_progress is None:
|
if not components:
|
||||||
setup_progress = hass.data['setup_progress'] = []
|
log_error('Unable to resolve component or dependencies')
|
||||||
|
|
||||||
if domain in setup_progress:
|
|
||||||
_LOGGER.error('Attempt made to setup %s during setup of %s',
|
|
||||||
domain, domain)
|
|
||||||
_async_persistent_notification(hass, domain, True)
|
|
||||||
return False
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Used to indicate to discovery that a setup is ongoing and allow it
|
|
||||||
# to wait till it is done.
|
|
||||||
did_lock = False
|
|
||||||
if not setup_lock.locked():
|
|
||||||
yield from setup_lock.acquire()
|
|
||||||
did_lock = True
|
|
||||||
|
|
||||||
setup_progress.append(domain)
|
|
||||||
config = yield from async_prepare_setup_component(hass, config, domain)
|
|
||||||
|
|
||||||
if config is None:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
component = loader.get_component(domain)
|
component = loader.get_component(domain)
|
||||||
if component is None:
|
|
||||||
_async_persistent_notification(hass, domain)
|
processed_config = \
|
||||||
|
conf_util.async_process_component_config(hass, config, domain)
|
||||||
|
|
||||||
|
if processed_config is None:
|
||||||
|
log_error('Invalid config')
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not hass.config.skip_pip and hasattr(component, 'REQUIREMENTS'):
|
||||||
|
req_success = yield from _async_process_requirements(
|
||||||
|
hass, domain, component.REQUIREMENTS)
|
||||||
|
if not req_success:
|
||||||
|
log_error('Could not install all requirements.')
|
||||||
|
return False
|
||||||
|
|
||||||
|
if hasattr(component, 'DEPENDENCIES'):
|
||||||
|
dep_success = yield from _async_process_dependencies(
|
||||||
|
hass, config, domain, component.DEPENDENCIES)
|
||||||
|
|
||||||
|
if not dep_success:
|
||||||
|
log_error('Could not setup all dependencies.')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async_comp = hasattr(component, 'async_setup')
|
async_comp = hasattr(component, 'async_setup')
|
||||||
@ -147,23 +187,21 @@ def _async_setup_component(hass: core.HomeAssistant,
|
|||||||
try:
|
try:
|
||||||
_LOGGER.info("Setting up %s", domain)
|
_LOGGER.info("Setting up %s", domain)
|
||||||
if async_comp:
|
if async_comp:
|
||||||
result = yield from component.async_setup(hass, config)
|
result = yield from component.async_setup(hass, processed_config)
|
||||||
else:
|
else:
|
||||||
result = yield from hass.loop.run_in_executor(
|
result = yield from hass.loop.run_in_executor(
|
||||||
None, component.setup, hass, config)
|
None, component.setup, hass, processed_config)
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.exception('Error during setup of component %s', domain)
|
_LOGGER.exception('Error during setup of component %s', domain)
|
||||||
_async_persistent_notification(hass, domain, True)
|
async_notify_setup_error(hass, domain, True)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if result is False:
|
if result is False:
|
||||||
_LOGGER.error('component %s failed to initialize', domain)
|
log_error('Component failed to initialize.')
|
||||||
_async_persistent_notification(hass, domain, True)
|
|
||||||
return False
|
return False
|
||||||
elif result is not True:
|
elif result is not True:
|
||||||
_LOGGER.error('component %s did not return boolean if setup '
|
log_error('Component did not return boolean if setup was successful. '
|
||||||
'was successful. Disabling component.', domain)
|
'Disabling component.')
|
||||||
_async_persistent_notification(hass, domain, True)
|
|
||||||
loader.set_component(domain, None)
|
loader.set_component(domain, None)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -174,102 +212,6 @@ def _async_setup_component(hass: core.HomeAssistant,
|
|||||||
)
|
)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
finally:
|
|
||||||
setup_progress.remove(domain)
|
|
||||||
if did_lock:
|
|
||||||
setup_lock.release()
|
|
||||||
|
|
||||||
|
|
||||||
def prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
|
||||||
domain: str):
|
|
||||||
"""Prepare setup of a component and return processed config."""
|
|
||||||
return run_coroutine_threadsafe(
|
|
||||||
async_prepare_setup_component(hass, config, domain), loop=hass.loop
|
|
||||||
).result()
|
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def async_prepare_setup_component(hass: core.HomeAssistant, config: dict,
|
|
||||||
domain: str):
|
|
||||||
"""Prepare setup of a component and return processed config.
|
|
||||||
|
|
||||||
This method is a coroutine.
|
|
||||||
"""
|
|
||||||
# pylint: disable=too-many-return-statements
|
|
||||||
component = loader.get_component(domain)
|
|
||||||
missing_deps = [dep for dep in getattr(component, 'DEPENDENCIES', [])
|
|
||||||
if dep not in hass.config.components]
|
|
||||||
|
|
||||||
if missing_deps:
|
|
||||||
_LOGGER.error(
|
|
||||||
'Not initializing %s because not all dependencies loaded: %s',
|
|
||||||
domain, ", ".join(missing_deps))
|
|
||||||
return None
|
|
||||||
|
|
||||||
if hasattr(component, 'CONFIG_SCHEMA'):
|
|
||||||
try:
|
|
||||||
config = component.CONFIG_SCHEMA(config)
|
|
||||||
except vol.Invalid as ex:
|
|
||||||
async_log_exception(ex, domain, config, hass)
|
|
||||||
return None
|
|
||||||
|
|
||||||
elif hasattr(component, 'PLATFORM_SCHEMA'):
|
|
||||||
platforms = []
|
|
||||||
for p_name, p_config in config_per_platform(config, domain):
|
|
||||||
# Validate component specific platform schema
|
|
||||||
try:
|
|
||||||
p_validated = component.PLATFORM_SCHEMA(p_config)
|
|
||||||
except vol.Invalid as ex:
|
|
||||||
async_log_exception(ex, domain, config, hass)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Not all platform components follow same pattern for platforms
|
|
||||||
# So if p_name is None we are not going to validate platform
|
|
||||||
# (the automation component is one of them)
|
|
||||||
if p_name is None:
|
|
||||||
platforms.append(p_validated)
|
|
||||||
continue
|
|
||||||
|
|
||||||
platform = yield from async_prepare_setup_platform(
|
|
||||||
hass, config, domain, p_name)
|
|
||||||
|
|
||||||
if platform is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Validate platform specific schema
|
|
||||||
if hasattr(platform, 'PLATFORM_SCHEMA'):
|
|
||||||
try:
|
|
||||||
# pylint: disable=no-member
|
|
||||||
p_validated = platform.PLATFORM_SCHEMA(p_validated)
|
|
||||||
except vol.Invalid as ex:
|
|
||||||
async_log_exception(ex, '{}.{}'.format(domain, p_name),
|
|
||||||
p_validated, hass)
|
|
||||||
continue
|
|
||||||
|
|
||||||
platforms.append(p_validated)
|
|
||||||
|
|
||||||
# Create a copy of the configuration with all config for current
|
|
||||||
# component removed and add validated config back in.
|
|
||||||
filter_keys = extract_domain_configs(config, domain)
|
|
||||||
config = {key: value for key, value in config.items()
|
|
||||||
if key not in filter_keys}
|
|
||||||
config[domain] = platforms
|
|
||||||
|
|
||||||
res = yield from hass.loop.run_in_executor(
|
|
||||||
None, _handle_requirements, hass, component, domain)
|
|
||||||
if not res:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return config
|
|
||||||
|
|
||||||
|
|
||||||
def prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
|
||||||
platform_name: str) -> Optional[ModuleType]:
|
|
||||||
"""Load a platform and makes sure dependencies are setup."""
|
|
||||||
return run_coroutine_threadsafe(
|
|
||||||
async_prepare_setup_platform(hass, config, domain, platform_name),
|
|
||||||
loop=hass.loop
|
|
||||||
).result()
|
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
@ -280,17 +222,19 @@ def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
|||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
if not loader.PREPARED:
|
|
||||||
yield from hass.loop.run_in_executor(None, loader.prepare, hass)
|
|
||||||
|
|
||||||
platform_path = PLATFORM_FORMAT.format(domain, platform_name)
|
platform_path = PLATFORM_FORMAT.format(domain, platform_name)
|
||||||
|
|
||||||
|
def log_error(msg):
|
||||||
|
"""Log helper."""
|
||||||
|
_LOGGER.error('Unable to prepare setup for platform %s: %s',
|
||||||
|
platform_path, msg)
|
||||||
|
async_notify_setup_error(hass, platform_path)
|
||||||
|
|
||||||
platform = loader.get_platform(domain, platform_name)
|
platform = loader.get_platform(domain, platform_name)
|
||||||
|
|
||||||
# Not found
|
# Not found
|
||||||
if platform is None:
|
if platform is None:
|
||||||
_LOGGER.error('Unable to find platform %s', platform_path)
|
log_error('Unable to find platform')
|
||||||
_async_persistent_notification(hass, platform_path)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Already loaded
|
# Already loaded
|
||||||
@ -298,23 +242,20 @@ def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
|||||||
return platform
|
return platform
|
||||||
|
|
||||||
# Load dependencies
|
# Load dependencies
|
||||||
for component in getattr(platform, 'DEPENDENCIES', []):
|
if hasattr(platform, 'DEPENDENCIES'):
|
||||||
if component in loader.DEPENDENCY_BLACKLIST:
|
dep_success = yield from _async_process_dependencies(
|
||||||
raise HomeAssistantError(
|
hass, config, platform_path, platform.DEPENDENCIES)
|
||||||
'{} is not allowed to be a dependency.'.format(component))
|
|
||||||
|
|
||||||
res = yield from async_setup_component(hass, component, config)
|
if not dep_success:
|
||||||
if not res:
|
log_error('Could not setup all dependencies.')
|
||||||
_LOGGER.error(
|
return False
|
||||||
'Unable to prepare setup for platform %s because '
|
|
||||||
'dependency %s could not be initialized', platform_path,
|
|
||||||
component)
|
|
||||||
_async_persistent_notification(hass, platform_path, True)
|
|
||||||
return None
|
|
||||||
|
|
||||||
res = yield from hass.loop.run_in_executor(
|
if not hass.config.skip_pip and hasattr(platform, 'REQUIREMENTS'):
|
||||||
None, _handle_requirements, hass, platform, platform_path)
|
req_success = yield from _async_process_requirements(
|
||||||
if not res:
|
hass, platform_path, platform.REQUIREMENTS)
|
||||||
|
|
||||||
|
if not req_success:
|
||||||
|
log_error('Could not install all requirements.')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return platform
|
return platform
|
||||||
@ -339,23 +280,14 @@ def from_config_dict(config: Dict[str, Any],
|
|||||||
hass.config.config_dir = config_dir
|
hass.config.config_dir = config_dir
|
||||||
mount_local_lib_path(config_dir)
|
mount_local_lib_path(config_dir)
|
||||||
|
|
||||||
@asyncio.coroutine
|
# run task
|
||||||
def _async_init_from_config_dict(future):
|
hass = hass.loop.run_until_complete(
|
||||||
try:
|
async_from_config_dict(
|
||||||
re_hass = yield from async_from_config_dict(
|
|
||||||
config, hass, config_dir, enable_log, verbose, skip_pip,
|
config, hass, config_dir, enable_log, verbose, skip_pip,
|
||||||
log_rotate_days)
|
log_rotate_days)
|
||||||
future.set_result(re_hass)
|
)
|
||||||
# pylint: disable=broad-except
|
|
||||||
except Exception as exc:
|
|
||||||
future.set_exception(exc)
|
|
||||||
|
|
||||||
# run task
|
return hass
|
||||||
future = asyncio.Future(loop=hass.loop)
|
|
||||||
hass.async_add_job(_async_init_from_config_dict(future))
|
|
||||||
hass.loop.run_until_complete(future)
|
|
||||||
|
|
||||||
return future.result()
|
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
@ -372,19 +304,15 @@ def async_from_config_dict(config: Dict[str, Any],
|
|||||||
Dynamically loads required components and its dependencies.
|
Dynamically loads required components and its dependencies.
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
|
start = time()
|
||||||
hass.async_track_tasks()
|
hass.async_track_tasks()
|
||||||
setup_lock = hass.data.get('setup_lock')
|
|
||||||
if setup_lock is None:
|
|
||||||
setup_lock = hass.data['setup_lock'] = asyncio.Lock(loop=hass.loop)
|
|
||||||
|
|
||||||
yield from setup_lock.acquire()
|
|
||||||
|
|
||||||
core_config = config.get(core.DOMAIN, {})
|
core_config = config.get(core.DOMAIN, {})
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yield from conf_util.async_process_ha_core_config(hass, core_config)
|
yield from conf_util.async_process_ha_core_config(hass, core_config)
|
||||||
except vol.Invalid as ex:
|
except vol.Invalid as ex:
|
||||||
async_log_exception(ex, 'homeassistant', core_config, hass)
|
conf_util.async_log_exception(ex, 'homeassistant', core_config, hass)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
yield from hass.loop.run_in_executor(
|
yield from hass.loop.run_in_executor(
|
||||||
@ -433,20 +361,25 @@ def async_from_config_dict(config: Dict[str, Any],
|
|||||||
event_decorators.HASS = hass
|
event_decorators.HASS = hass
|
||||||
service.HASS = hass
|
service.HASS = hass
|
||||||
|
|
||||||
# Setup the components
|
# stage 1
|
||||||
dependency_blacklist = loader.DEPENDENCY_BLACKLIST - set(components)
|
for component in components:
|
||||||
|
if component not in FIRST_INIT_COMPONENT:
|
||||||
|
continue
|
||||||
|
hass.async_add_job(async_setup_component(hass, component, config))
|
||||||
|
|
||||||
for domain in loader.load_order_components(components):
|
yield from hass.async_block_till_done()
|
||||||
if domain in dependency_blacklist:
|
|
||||||
raise HomeAssistantError(
|
|
||||||
'{} is not allowed to be a dependency'.format(domain))
|
|
||||||
|
|
||||||
yield from _async_setup_component(hass, domain, config)
|
# stage 2
|
||||||
|
for component in components:
|
||||||
setup_lock.release()
|
if component in FIRST_INIT_COMPONENT:
|
||||||
|
continue
|
||||||
|
hass.async_add_job(async_setup_component(hass, component, config))
|
||||||
|
|
||||||
yield from hass.async_stop_track_tasks()
|
yield from hass.async_stop_track_tasks()
|
||||||
|
|
||||||
|
stop = time()
|
||||||
|
_LOGGER.info('Home Assistant initialized in %ss', round(stop-start, 2))
|
||||||
|
|
||||||
async_register_signal_handling(hass)
|
async_register_signal_handling(hass)
|
||||||
return hass
|
return hass
|
||||||
|
|
||||||
@ -464,22 +397,13 @@ def from_config_file(config_path: str,
|
|||||||
if hass is None:
|
if hass is None:
|
||||||
hass = core.HomeAssistant()
|
hass = core.HomeAssistant()
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def _async_init_from_config_file(future):
|
|
||||||
try:
|
|
||||||
re_hass = yield from async_from_config_file(
|
|
||||||
config_path, hass, verbose, skip_pip, log_rotate_days)
|
|
||||||
future.set_result(re_hass)
|
|
||||||
# pylint: disable=broad-except
|
|
||||||
except Exception as exc:
|
|
||||||
future.set_exception(exc)
|
|
||||||
|
|
||||||
# run task
|
# run task
|
||||||
future = asyncio.Future(loop=hass.loop)
|
hass = hass.loop.run_until_complete(
|
||||||
hass.loop.create_task(_async_init_from_config_file(future))
|
async_from_config_file(
|
||||||
hass.loop.run_until_complete(future)
|
config_path, hass, verbose, skip_pip, log_rotate_days)
|
||||||
|
)
|
||||||
|
|
||||||
return future.result()
|
return hass
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
@ -588,62 +512,6 @@ def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False,
|
|||||||
'Unable to setup error log %s (access denied)', err_log_path)
|
'Unable to setup error log %s (access denied)', err_log_path)
|
||||||
|
|
||||||
|
|
||||||
def log_exception(ex, domain, config, hass):
|
|
||||||
"""Generate log exception for config validation."""
|
|
||||||
run_callback_threadsafe(
|
|
||||||
hass.loop, async_log_exception, ex, domain, config, hass).result()
|
|
||||||
|
|
||||||
|
|
||||||
@core.callback
|
|
||||||
def _async_persistent_notification(hass: core.HomeAssistant, component: str,
|
|
||||||
link: Optional[bool]=False):
|
|
||||||
"""Print a persistent notification.
|
|
||||||
|
|
||||||
This method must be run in the event loop.
|
|
||||||
"""
|
|
||||||
errors = hass.data.get(DATA_PERSISTENT_ERRORS)
|
|
||||||
|
|
||||||
if errors is None:
|
|
||||||
errors = hass.data[DATA_PERSISTENT_ERRORS] = {}
|
|
||||||
|
|
||||||
errors[component] = errors.get(component) or link
|
|
||||||
_lst = [HA_COMPONENT_URL.format(name.replace('_', '-'), name)
|
|
||||||
if link else name for name, link in errors.items()]
|
|
||||||
message = ('The following components and platforms could not be set up:\n'
|
|
||||||
'* ' + '\n* '.join(list(_lst)) + '\nPlease check your config')
|
|
||||||
persistent_notification.async_create(
|
|
||||||
hass, message, 'Invalid config', 'invalid_config')
|
|
||||||
|
|
||||||
|
|
||||||
@core.callback
|
|
||||||
def async_log_exception(ex, domain, config, hass):
|
|
||||||
"""Generate log exception for config validation.
|
|
||||||
|
|
||||||
This method must be run in the event loop.
|
|
||||||
"""
|
|
||||||
message = 'Invalid config for [{}]: '.format(domain)
|
|
||||||
if hass is not None:
|
|
||||||
_async_persistent_notification(hass, domain, True)
|
|
||||||
|
|
||||||
if 'extra keys not allowed' in ex.error_message:
|
|
||||||
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\
|
|
||||||
.format(ex.path[-1], domain, domain,
|
|
||||||
'->'.join(str(m) for m in ex.path))
|
|
||||||
else:
|
|
||||||
message += '{}.'.format(humanize_error(config, ex))
|
|
||||||
|
|
||||||
domain_config = config.get(domain, config)
|
|
||||||
message += " (See {}, line {}). ".format(
|
|
||||||
getattr(domain_config, '__config_file__', '?'),
|
|
||||||
getattr(domain_config, '__line__', '?'))
|
|
||||||
|
|
||||||
if domain != 'homeassistant':
|
|
||||||
message += ('Please check the docs at '
|
|
||||||
'https://home-assistant.io/components/{}/'.format(domain))
|
|
||||||
|
|
||||||
_LOGGER.error(message)
|
|
||||||
|
|
||||||
|
|
||||||
def mount_local_lib_path(config_dir: str) -> str:
|
def mount_local_lib_path(config_dir: str) -> str:
|
||||||
"""Add local library to Python Path.
|
"""Add local library to Python Path.
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
)
|
)
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
|
|
||||||
yield from async_add_devices(devices)
|
async_add_devices(devices)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def alarm_keypress_handler(service):
|
def alarm_keypress_handler(service):
|
||||||
|
@ -46,7 +46,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup the MQTT platform."""
|
"""Setup the MQTT platform."""
|
||||||
yield from async_add_devices([MqttAlarm(
|
async_add_devices([MqttAlarm(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
config.get(CONF_STATE_TOPIC),
|
config.get(CONF_STATE_TOPIC),
|
||||||
config.get(CONF_COMMAND_TOPIC),
|
config.get(CONF_COMMAND_TOPIC),
|
||||||
|
@ -28,8 +28,6 @@ import homeassistant.helpers.config_validation as cv
|
|||||||
DOMAIN = 'automation'
|
DOMAIN = 'automation'
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
|
|
||||||
DEPENDENCIES = ['group']
|
|
||||||
|
|
||||||
GROUP_NAME_ALL_AUTOMATIONS = 'all automations'
|
GROUP_NAME_ALL_AUTOMATIONS = 'all automations'
|
||||||
|
|
||||||
CONF_ALIAS = 'alias'
|
CONF_ALIAS = 'alias'
|
||||||
@ -226,7 +224,7 @@ class AutomationEntity(ToggleEntity):
|
|||||||
"""Entity to show status of entity."""
|
"""Entity to show status of entity."""
|
||||||
|
|
||||||
def __init__(self, name, async_attach_triggers, cond_func, async_action,
|
def __init__(self, name, async_attach_triggers, cond_func, async_action,
|
||||||
hidden):
|
hidden, initial_state):
|
||||||
"""Initialize an automation entity."""
|
"""Initialize an automation entity."""
|
||||||
self._name = name
|
self._name = name
|
||||||
self._async_attach_triggers = async_attach_triggers
|
self._async_attach_triggers = async_attach_triggers
|
||||||
@ -236,6 +234,7 @@ class AutomationEntity(ToggleEntity):
|
|||||||
self._enabled = False
|
self._enabled = False
|
||||||
self._last_triggered = None
|
self._last_triggered = None
|
||||||
self._hidden = hidden
|
self._hidden = hidden
|
||||||
|
self._initial_state = initial_state
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@ -264,6 +263,12 @@ class AutomationEntity(ToggleEntity):
|
|||||||
"""Return True if entity is on."""
|
"""Return True if entity is on."""
|
||||||
return self._enabled
|
return self._enabled
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_added_to_hass(self) -> None:
|
||||||
|
"""Startup if initial_state."""
|
||||||
|
if self._initial_state:
|
||||||
|
yield from self.async_enable()
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_turn_on(self, **kwargs) -> None:
|
def async_turn_on(self, **kwargs) -> None:
|
||||||
"""Turn the entity on and update the state."""
|
"""Turn the entity on and update the state."""
|
||||||
@ -322,7 +327,6 @@ def _async_process_config(hass, config, component):
|
|||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
entities = []
|
entities = []
|
||||||
tasks = []
|
|
||||||
|
|
||||||
for config_key in extract_domain_configs(config, DOMAIN):
|
for config_key in extract_domain_configs(config, DOMAIN):
|
||||||
conf = config[config_key]
|
conf = config[config_key]
|
||||||
@ -332,6 +336,7 @@ def _async_process_config(hass, config, component):
|
|||||||
list_no)
|
list_no)
|
||||||
|
|
||||||
hidden = config_block[CONF_HIDE_ENTITY]
|
hidden = config_block[CONF_HIDE_ENTITY]
|
||||||
|
initial_state = config_block[CONF_INITIAL_STATE]
|
||||||
|
|
||||||
action = _async_get_action(hass, config_block.get(CONF_ACTION, {}),
|
action = _async_get_action(hass, config_block.get(CONF_ACTION, {}),
|
||||||
name)
|
name)
|
||||||
@ -348,15 +353,14 @@ def _async_process_config(hass, config, component):
|
|||||||
|
|
||||||
async_attach_triggers = partial(
|
async_attach_triggers = partial(
|
||||||
_async_process_trigger, hass, config,
|
_async_process_trigger, hass, config,
|
||||||
config_block.get(CONF_TRIGGER, []), name)
|
config_block.get(CONF_TRIGGER, []), name
|
||||||
entity = AutomationEntity(name, async_attach_triggers, cond_func,
|
)
|
||||||
action, hidden)
|
entity = AutomationEntity(
|
||||||
if config_block[CONF_INITIAL_STATE]:
|
name, async_attach_triggers, cond_func, action, hidden,
|
||||||
tasks.append(entity.async_enable())
|
initial_state)
|
||||||
|
|
||||||
entities.append(entity)
|
entities.append(entity)
|
||||||
|
|
||||||
if tasks:
|
|
||||||
yield from asyncio.wait(tasks, loop=hass.loop)
|
|
||||||
if entities:
|
if entities:
|
||||||
yield from component.async_add_entities(entities)
|
yield from component.async_add_entities(entities)
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
)
|
)
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
|
|
||||||
yield from async_add_devices(devices)
|
async_add_devices(devices)
|
||||||
|
|
||||||
|
|
||||||
class EnvisalinkBinarySensor(EnvisalinkDevice, BinarySensorDevice):
|
class EnvisalinkBinarySensor(EnvisalinkDevice, BinarySensorDevice):
|
||||||
|
@ -57,7 +57,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
|
|
||||||
# generate sensor object
|
# generate sensor object
|
||||||
entity = FFmpegMotion(hass, manager, config)
|
entity = FFmpegMotion(hass, manager, config)
|
||||||
yield from async_add_devices([entity])
|
async_add_devices([entity])
|
||||||
|
|
||||||
|
|
||||||
class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice):
|
class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice):
|
||||||
|
@ -54,7 +54,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
|
|
||||||
# generate sensor object
|
# generate sensor object
|
||||||
entity = FFmpegNoise(hass, manager, config)
|
entity = FFmpegNoise(hass, manager, config)
|
||||||
yield from async_add_devices([entity])
|
async_add_devices([entity])
|
||||||
|
|
||||||
|
|
||||||
class FFmpegNoise(FFmpegBinarySensor):
|
class FFmpegNoise(FFmpegBinarySensor):
|
||||||
|
@ -46,7 +46,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
yield from async_add_devices([MqttBinarySensor(
|
async_add_devices([MqttBinarySensor(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
config.get(CONF_STATE_TOPIC),
|
config.get(CONF_STATE_TOPIC),
|
||||||
get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS),
|
get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS),
|
||||||
|
@ -66,7 +66,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
_LOGGER.error('No sensors added')
|
_LOGGER.error('No sensors added')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
yield from async_add_devices(sensors, True)
|
async_add_devices(sensors, True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
limit_type = config.get(CONF_TYPE)
|
limit_type = config.get(CONF_TYPE)
|
||||||
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
|
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
|
||||||
|
|
||||||
yield from async_add_devices(
|
async_add_devices(
|
||||||
[ThresholdSensor(hass, entity_id, name, threshold, limit_type,
|
[ThresholdSensor(hass, entity_id, name, threshold, limit_type,
|
||||||
device_class)], True)
|
device_class)], True)
|
||||||
return True
|
return True
|
||||||
|
@ -34,7 +34,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
"""Setup a FFmpeg Camera."""
|
"""Setup a FFmpeg Camera."""
|
||||||
if not hass.data[DATA_FFMPEG].async_run_test(config.get(CONF_INPUT)):
|
if not hass.data[DATA_FFMPEG].async_run_test(config.get(CONF_INPUT)):
|
||||||
return
|
return
|
||||||
yield from async_add_devices([FFmpegCamera(hass, config)])
|
async_add_devices([FFmpegCamera(hass, config)])
|
||||||
|
|
||||||
|
|
||||||
class FFmpegCamera(Camera):
|
class FFmpegCamera(Camera):
|
||||||
|
@ -44,7 +44,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup a generic IP Camera."""
|
"""Setup a generic IP Camera."""
|
||||||
yield from async_add_devices([GenericCamera(hass, config)])
|
async_add_devices([GenericCamera(hass, config)])
|
||||||
|
|
||||||
|
|
||||||
class GenericCamera(Camera):
|
class GenericCamera(Camera):
|
||||||
|
@ -45,7 +45,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup a MJPEG IP Camera."""
|
"""Setup a MJPEG IP Camera."""
|
||||||
yield from async_add_devices([MjpegCamera(hass, config)])
|
async_add_devices([MjpegCamera(hass, config)])
|
||||||
|
|
||||||
|
|
||||||
def extract_image_from_mjpeg(stream):
|
def extract_image_from_mjpeg(stream):
|
||||||
|
@ -153,7 +153,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
)
|
)
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
|
|
||||||
yield from async_add_devices(devices)
|
async_add_devices(devices)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
|
@ -75,4 +75,4 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
_LOGGER.warning('No active cameras found')
|
_LOGGER.warning('No active cameras found')
|
||||||
return
|
return
|
||||||
|
|
||||||
yield from async_add_devices(cameras)
|
async_add_devices(cameras)
|
||||||
|
@ -63,7 +63,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
min_cycle_duration = config.get(CONF_MIN_DUR)
|
min_cycle_duration = config.get(CONF_MIN_DUR)
|
||||||
tolerance = config.get(CONF_TOLERANCE)
|
tolerance = config.get(CONF_TOLERANCE)
|
||||||
|
|
||||||
yield from async_add_devices([GenericThermostat(
|
async_add_devices([GenericThermostat(
|
||||||
hass, name, heater_entity_id, sensor_entity_id, min_temp, max_temp,
|
hass, name, heater_entity_id, sensor_entity_id, min_temp, max_temp,
|
||||||
target_temp, ac_mode, min_cycle_duration, tolerance)])
|
target_temp, ac_mode, min_cycle_duration, tolerance)])
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
yield from async_add_devices([MqttCover(
|
async_add_devices([MqttCover(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
config.get(CONF_STATE_TOPIC),
|
config.get(CONF_STATE_TOPIC),
|
||||||
config.get(CONF_COMMAND_TOPIC),
|
config.get(CONF_COMMAND_TOPIC),
|
||||||
|
@ -4,6 +4,7 @@ Sets up a demo environment that mimics interaction with devices.
|
|||||||
For more details about this component, please refer to the documentation
|
For more details about this component, please refer to the documentation
|
||||||
https://home-assistant.io/components/demo/
|
https://home-assistant.io/components/demo/
|
||||||
"""
|
"""
|
||||||
|
import asyncio
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import homeassistant.bootstrap as bootstrap
|
import homeassistant.bootstrap as bootstrap
|
||||||
@ -34,7 +35,8 @@ COMPONENTS_WITH_DEMO_PLATFORM = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def setup(hass, config):
|
@asyncio.coroutine
|
||||||
|
def async_setup(hass, config):
|
||||||
"""Setup a demo environment."""
|
"""Setup a demo environment."""
|
||||||
group = loader.get_component('group')
|
group = loader.get_component('group')
|
||||||
configurator = loader.get_component('configurator')
|
configurator = loader.get_component('configurator')
|
||||||
@ -44,7 +46,7 @@ def setup(hass, config):
|
|||||||
config.setdefault(DOMAIN, {})
|
config.setdefault(DOMAIN, {})
|
||||||
|
|
||||||
if config[DOMAIN].get('hide_demo_state') != 1:
|
if config[DOMAIN].get('hide_demo_state') != 1:
|
||||||
hass.states.set('a.Demo_Mode', 'Enabled')
|
hass.states.async_set('a.Demo_Mode', 'Enabled')
|
||||||
|
|
||||||
# Setup sun
|
# Setup sun
|
||||||
if not hass.config.latitude:
|
if not hass.config.latitude:
|
||||||
@ -53,50 +55,71 @@ def setup(hass, config):
|
|||||||
if not hass.config.longitude:
|
if not hass.config.longitude:
|
||||||
hass.config.longitude = 117.22743
|
hass.config.longitude = 117.22743
|
||||||
|
|
||||||
bootstrap.setup_component(hass, 'sun')
|
tasks = [
|
||||||
|
bootstrap.async_setup_component(hass, 'sun')
|
||||||
|
]
|
||||||
|
|
||||||
# Setup demo platforms
|
# Setup demo platforms
|
||||||
demo_config = config.copy()
|
demo_config = config.copy()
|
||||||
for component in COMPONENTS_WITH_DEMO_PLATFORM:
|
for component in COMPONENTS_WITH_DEMO_PLATFORM:
|
||||||
demo_config[component] = {CONF_PLATFORM: 'demo'}
|
demo_config[component] = {CONF_PLATFORM: 'demo'}
|
||||||
bootstrap.setup_component(hass, component, demo_config)
|
tasks.append(
|
||||||
|
bootstrap.async_setup_component(hass, component, demo_config))
|
||||||
|
|
||||||
|
# Set up input select
|
||||||
|
tasks.append(bootstrap.async_setup_component(
|
||||||
|
hass, 'input_select',
|
||||||
|
{'input_select':
|
||||||
|
{'living_room_preset': {'options': ['Visitors',
|
||||||
|
'Visitors with kids',
|
||||||
|
'Home Alone']},
|
||||||
|
'who_cooks': {'icon': 'mdi:panda',
|
||||||
|
'initial': 'Anne Therese',
|
||||||
|
'name': 'Cook today',
|
||||||
|
'options': ['Paulus', 'Anne Therese']}}}))
|
||||||
|
# Set up input boolean
|
||||||
|
tasks.append(bootstrap.async_setup_component(
|
||||||
|
hass, 'input_boolean',
|
||||||
|
{'input_boolean': {'notify': {
|
||||||
|
'icon': 'mdi:car',
|
||||||
|
'initial': False,
|
||||||
|
'name': 'Notify Anne Therese is home'}}}))
|
||||||
|
|
||||||
|
# Set up input boolean
|
||||||
|
tasks.append(bootstrap.async_setup_component(
|
||||||
|
hass, 'input_slider',
|
||||||
|
{'input_slider': {
|
||||||
|
'noise_allowance': {'icon': 'mdi:bell-ring',
|
||||||
|
'min': 0,
|
||||||
|
'max': 10,
|
||||||
|
'name': 'Allowed Noise',
|
||||||
|
'unit_of_measurement': 'dB'}}}))
|
||||||
|
|
||||||
|
# Set up weblink
|
||||||
|
tasks.append(bootstrap.async_setup_component(
|
||||||
|
hass, 'weblink',
|
||||||
|
{'weblink': {'entities': [{'name': 'Router',
|
||||||
|
'url': 'http://192.168.1.1'}]}}))
|
||||||
|
|
||||||
|
results = yield from asyncio.gather(*tasks, loop=hass.loop)
|
||||||
|
|
||||||
|
if any(not result for result in results):
|
||||||
|
return False
|
||||||
|
|
||||||
# Setup example persistent notification
|
# Setup example persistent notification
|
||||||
persistent_notification.create(
|
persistent_notification.async_create(
|
||||||
hass, 'This is an example of a persistent notification.',
|
hass, 'This is an example of a persistent notification.',
|
||||||
title='Example Notification')
|
title='Example Notification')
|
||||||
|
|
||||||
# Setup room groups
|
# Setup room groups
|
||||||
lights = sorted(hass.states.entity_ids('light'))
|
lights = sorted(hass.states.async_entity_ids('light'))
|
||||||
switches = sorted(hass.states.entity_ids('switch'))
|
switches = sorted(hass.states.async_entity_ids('switch'))
|
||||||
media_players = sorted(hass.states.entity_ids('media_player'))
|
media_players = sorted(hass.states.async_entity_ids('media_player'))
|
||||||
|
|
||||||
group.Group.create_group(hass, 'living room', [
|
tasks2 = []
|
||||||
lights[1], switches[0], 'input_select.living_room_preset',
|
|
||||||
'rollershutter.living_room_window', media_players[1],
|
|
||||||
'scene.romantic_lights'])
|
|
||||||
group.Group.create_group(hass, 'bedroom', [
|
|
||||||
lights[0], switches[1], media_players[0],
|
|
||||||
'input_slider.noise_allowance'])
|
|
||||||
group.Group.create_group(hass, 'kitchen', [
|
|
||||||
lights[2], 'rollershutter.kitchen_window', 'lock.kitchen_door'])
|
|
||||||
group.Group.create_group(hass, 'doors', [
|
|
||||||
'lock.front_door', 'lock.kitchen_door',
|
|
||||||
'garage_door.right_garage_door', 'garage_door.left_garage_door'])
|
|
||||||
group.Group.create_group(hass, 'automations', [
|
|
||||||
'input_select.who_cooks', 'input_boolean.notify', ])
|
|
||||||
group.Group.create_group(hass, 'people', [
|
|
||||||
'device_tracker.demo_anne_therese', 'device_tracker.demo_home_boy',
|
|
||||||
'device_tracker.demo_paulus'])
|
|
||||||
group.Group.create_group(hass, 'downstairs', [
|
|
||||||
'group.living_room', 'group.kitchen',
|
|
||||||
'scene.romantic_lights', 'rollershutter.kitchen_window',
|
|
||||||
'rollershutter.living_room_window', 'group.doors',
|
|
||||||
'thermostat.ecobee',
|
|
||||||
], view=True)
|
|
||||||
|
|
||||||
# Setup scripts
|
# Setup scripts
|
||||||
bootstrap.setup_component(
|
tasks2.append(bootstrap.async_setup_component(
|
||||||
hass, 'script',
|
hass, 'script',
|
||||||
{'script': {
|
{'script': {
|
||||||
'demo': {
|
'demo': {
|
||||||
@ -115,10 +138,10 @@ def setup(hass, config):
|
|||||||
'service': 'light.turn_off',
|
'service': 'light.turn_off',
|
||||||
'data': {ATTR_ENTITY_ID: lights[0]}
|
'data': {ATTR_ENTITY_ID: lights[0]}
|
||||||
}]
|
}]
|
||||||
}}})
|
}}}))
|
||||||
|
|
||||||
# Setup scenes
|
# Setup scenes
|
||||||
bootstrap.setup_component(
|
tasks2.append(bootstrap.async_setup_component(
|
||||||
hass, 'scene',
|
hass, 'scene',
|
||||||
{'scene': [
|
{'scene': [
|
||||||
{'name': 'Romantic lights',
|
{'name': 'Romantic lights',
|
||||||
@ -132,41 +155,37 @@ def setup(hass, config):
|
|||||||
switches[0]: True,
|
switches[0]: True,
|
||||||
switches[1]: False,
|
switches[1]: False,
|
||||||
}},
|
}},
|
||||||
]})
|
]}))
|
||||||
|
|
||||||
# Set up input select
|
tasks2.append(group.Group.async_create_group(hass, 'living room', [
|
||||||
bootstrap.setup_component(
|
lights[1], switches[0], 'input_select.living_room_preset',
|
||||||
hass, 'input_select',
|
'rollershutter.living_room_window', media_players[1],
|
||||||
{'input_select':
|
'scene.romantic_lights']))
|
||||||
{'living_room_preset': {'options': ['Visitors',
|
tasks2.append(group.Group.async_create_group(hass, 'bedroom', [
|
||||||
'Visitors with kids',
|
lights[0], switches[1], media_players[0],
|
||||||
'Home Alone']},
|
'input_slider.noise_allowance']))
|
||||||
'who_cooks': {'icon': 'mdi:panda',
|
tasks2.append(group.Group.async_create_group(hass, 'kitchen', [
|
||||||
'initial': 'Anne Therese',
|
lights[2], 'rollershutter.kitchen_window', 'lock.kitchen_door']))
|
||||||
'name': 'Cook today',
|
tasks2.append(group.Group.async_create_group(hass, 'doors', [
|
||||||
'options': ['Paulus', 'Anne Therese']}}})
|
'lock.front_door', 'lock.kitchen_door',
|
||||||
# Set up input boolean
|
'garage_door.right_garage_door', 'garage_door.left_garage_door']))
|
||||||
bootstrap.setup_component(
|
tasks2.append(group.Group.async_create_group(hass, 'automations', [
|
||||||
hass, 'input_boolean',
|
'input_select.who_cooks', 'input_boolean.notify', ]))
|
||||||
{'input_boolean': {'notify': {'icon': 'mdi:car',
|
tasks2.append(group.Group.async_create_group(hass, 'people', [
|
||||||
'initial': False,
|
'device_tracker.demo_anne_therese', 'device_tracker.demo_home_boy',
|
||||||
'name': 'Notify Anne Therese is home'}}})
|
'device_tracker.demo_paulus']))
|
||||||
|
tasks2.append(group.Group.async_create_group(hass, 'downstairs', [
|
||||||
|
'group.living_room', 'group.kitchen',
|
||||||
|
'scene.romantic_lights', 'rollershutter.kitchen_window',
|
||||||
|
'rollershutter.living_room_window', 'group.doors',
|
||||||
|
'thermostat.ecobee',
|
||||||
|
], view=True))
|
||||||
|
|
||||||
# Set up input boolean
|
results = yield from asyncio.gather(*tasks2, loop=hass.loop)
|
||||||
bootstrap.setup_component(
|
|
||||||
hass, 'input_slider',
|
if any(not result for result in results):
|
||||||
{'input_slider': {
|
return False
|
||||||
'noise_allowance': {'icon': 'mdi:bell-ring',
|
|
||||||
'min': 0,
|
|
||||||
'max': 10,
|
|
||||||
'name': 'Allowed Noise',
|
|
||||||
'unit_of_measurement': 'dB'}}})
|
|
||||||
|
|
||||||
# Set up weblink
|
|
||||||
bootstrap.setup_component(
|
|
||||||
hass, 'weblink',
|
|
||||||
{'weblink': {'entities': [{'name': 'Router',
|
|
||||||
'url': 'http://192.168.1.1'}]}})
|
|
||||||
# Setup configurator
|
# Setup configurator
|
||||||
configurator_ids = []
|
configurator_ids = []
|
||||||
|
|
||||||
@ -184,14 +203,17 @@ def setup(hass, config):
|
|||||||
else:
|
else:
|
||||||
configurator.request_done(configurator_ids[0])
|
configurator.request_done(configurator_ids[0])
|
||||||
|
|
||||||
|
def setup_configurator():
|
||||||
|
"""Setup configurator."""
|
||||||
request_id = configurator.request_config(
|
request_id = configurator.request_config(
|
||||||
hass, "Philips Hue", hue_configuration_callback,
|
hass, "Philips Hue", hue_configuration_callback,
|
||||||
description=("Press the button on the bridge to register Philips Hue "
|
description=("Press the button on the bridge to register Philips "
|
||||||
"with Home Assistant."),
|
"Hue with Home Assistant."),
|
||||||
description_image="/static/images/config_philips_hue.jpg",
|
description_image="/static/images/config_philips_hue.jpg",
|
||||||
submit_caption="I have pressed the button"
|
submit_caption="I have pressed the button"
|
||||||
)
|
)
|
||||||
|
|
||||||
configurator_ids.append(request_id)
|
configurator_ids.append(request_id)
|
||||||
|
|
||||||
|
hass.async_add_job(setup_configurator)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -14,12 +14,11 @@ import aiohttp
|
|||||||
import async_timeout
|
import async_timeout
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.bootstrap import (
|
from homeassistant.bootstrap import async_prepare_setup_platform
|
||||||
async_prepare_setup_platform, async_log_exception)
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.components import group, zone
|
from homeassistant.components import group, zone
|
||||||
from homeassistant.components.discovery import SERVICE_NETGEAR
|
from homeassistant.components.discovery import SERVICE_NETGEAR
|
||||||
from homeassistant.config import load_yaml_config_file
|
from homeassistant.config import load_yaml_config_file, async_log_exception
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers import config_per_platform, discovery
|
from homeassistant.helpers import config_per_platform, discovery
|
||||||
|
@ -78,7 +78,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend({
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup MQTT fan platform."""
|
"""Setup MQTT fan platform."""
|
||||||
yield from async_add_devices([MqttFan(
|
async_add_devices([MqttFan(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
{
|
{
|
||||||
key: config.get(key) for key in (
|
key: config.get(key) for key in (
|
||||||
|
@ -60,7 +60,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
camera[CONF_ENTITY_ID], api, attributes, camera.get(CONF_NAME)
|
camera[CONF_ENTITY_ID], api, attributes, camera.get(CONF_NAME)
|
||||||
))
|
))
|
||||||
|
|
||||||
yield from async_add_devices(entities)
|
async_add_devices(entities)
|
||||||
|
|
||||||
|
|
||||||
class MicrosoftFaceDetectEntity(ImageProcessingFaceEntity):
|
class MicrosoftFaceDetectEntity(ImageProcessingFaceEntity):
|
||||||
|
@ -54,7 +54,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
camera.get(CONF_NAME)
|
camera.get(CONF_NAME)
|
||||||
))
|
))
|
||||||
|
|
||||||
yield from async_add_devices(entities)
|
async_add_devices(entities)
|
||||||
|
|
||||||
|
|
||||||
class ImageProcessingFaceEntity(ImageProcessingEntity):
|
class ImageProcessingFaceEntity(ImageProcessingEntity):
|
||||||
|
@ -66,7 +66,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
camera[CONF_ENTITY_ID], params, confidence, camera.get(CONF_NAME)
|
camera[CONF_ENTITY_ID], params, confidence, camera.get(CONF_NAME)
|
||||||
))
|
))
|
||||||
|
|
||||||
yield from async_add_devices(entities)
|
async_add_devices(entities)
|
||||||
|
|
||||||
|
|
||||||
class OpenAlprCloudEntity(ImageProcessingAlprEntity):
|
class OpenAlprCloudEntity(ImageProcessingAlprEntity):
|
||||||
|
@ -70,7 +70,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
camera[CONF_ENTITY_ID], command, confidence, camera.get(CONF_NAME)
|
camera[CONF_ENTITY_ID], command, confidence, camera.get(CONF_NAME)
|
||||||
))
|
))
|
||||||
|
|
||||||
yield from async_add_devices(entities)
|
async_add_devices(entities)
|
||||||
|
|
||||||
|
|
||||||
class ImageProcessingAlprEntity(ImageProcessingEntity):
|
class ImageProcessingAlprEntity(ImageProcessingEntity):
|
||||||
|
@ -70,7 +70,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
config.setdefault(
|
config.setdefault(
|
||||||
CONF_STATE_VALUE_TEMPLATE, config.get(CONF_VALUE_TEMPLATE))
|
CONF_STATE_VALUE_TEMPLATE, config.get(CONF_VALUE_TEMPLATE))
|
||||||
|
|
||||||
yield from async_add_devices([MqttLight(
|
async_add_devices([MqttLight(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
{
|
{
|
||||||
key: config.get(key) for key in (
|
key: config.get(key) for key in (
|
||||||
|
@ -61,7 +61,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup a MQTT JSON Light."""
|
"""Setup a MQTT JSON Light."""
|
||||||
yield from async_add_devices([MqttJson(
|
async_add_devices([MqttJson(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
{
|
{
|
||||||
key: config.get(key) for key in (
|
key: config.get(key) for key in (
|
||||||
|
@ -64,7 +64,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup a MQTT Template light."""
|
"""Setup a MQTT Template light."""
|
||||||
yield from async_add_devices([MqttTemplate(
|
async_add_devices([MqttTemplate(
|
||||||
hass,
|
hass,
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
config.get(CONF_EFFECT_LIST),
|
config.get(CONF_EFFECT_LIST),
|
||||||
|
@ -117,7 +117,7 @@ def devices_from_config(domain_config, hass=None):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Set up the Rflink light platform."""
|
"""Set up the Rflink light platform."""
|
||||||
yield from async_add_devices(devices_from_config(config, hass))
|
async_add_devices(devices_from_config(config, hass))
|
||||||
|
|
||||||
# Add new (unconfigured) devices to user desired group
|
# Add new (unconfigured) devices to user desired group
|
||||||
if config[CONF_NEW_DEVICES_GROUP]:
|
if config[CONF_NEW_DEVICES_GROUP]:
|
||||||
@ -136,7 +136,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
|
|
||||||
device_config = config[CONF_DEVICE_DEFAULTS]
|
device_config = config[CONF_DEVICE_DEFAULTS]
|
||||||
device = entity_class(device_id, hass, **device_config)
|
device = entity_class(device_id, hass, **device_config)
|
||||||
yield from async_add_devices([device])
|
async_add_devices([device])
|
||||||
|
|
||||||
# Register entity to listen to incoming Rflink events
|
# Register entity to listen to incoming Rflink events
|
||||||
hass.data[DATA_ENTITY_LOOKUP][
|
hass.data[DATA_ENTITY_LOOKUP][
|
||||||
@ -156,7 +156,10 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
class RflinkLight(SwitchableRflinkDevice, Light):
|
class RflinkLight(SwitchableRflinkDevice, Light):
|
||||||
"""Representation of a Rflink light."""
|
"""Representation of a Rflink light."""
|
||||||
|
|
||||||
pass
|
@property
|
||||||
|
def entity_id(self):
|
||||||
|
"""Return entity id."""
|
||||||
|
return "light.{}".format(self.name)
|
||||||
|
|
||||||
|
|
||||||
class DimmableRflinkLight(SwitchableRflinkDevice, Light):
|
class DimmableRflinkLight(SwitchableRflinkDevice, Light):
|
||||||
@ -164,6 +167,11 @@ class DimmableRflinkLight(SwitchableRflinkDevice, Light):
|
|||||||
|
|
||||||
_brightness = 255
|
_brightness = 255
|
||||||
|
|
||||||
|
@property
|
||||||
|
def entity_id(self):
|
||||||
|
"""Return entity id."""
|
||||||
|
return "light.{}".format(self.name)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_turn_on(self, **kwargs):
|
def async_turn_on(self, **kwargs):
|
||||||
"""Turn the device on."""
|
"""Turn the device on."""
|
||||||
@ -202,6 +210,11 @@ class HybridRflinkLight(SwitchableRflinkDevice, Light):
|
|||||||
|
|
||||||
_brightness = 255
|
_brightness = 255
|
||||||
|
|
||||||
|
@property
|
||||||
|
def entity_id(self):
|
||||||
|
"""Return entity id."""
|
||||||
|
return "light.{}".format(self.name)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_turn_on(self, **kwargs):
|
def async_turn_on(self, **kwargs):
|
||||||
"""Turn the device on and set dim level."""
|
"""Turn the device on and set dim level."""
|
||||||
|
@ -47,7 +47,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
yield from async_add_devices([MqttLock(
|
async_add_devices([MqttLock(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
config.get(CONF_STATE_TOPIC),
|
config.get(CONF_STATE_TOPIC),
|
||||||
config.get(CONF_COMMAND_TOPIC),
|
config.get(CONF_COMMAND_TOPIC),
|
||||||
|
@ -63,7 +63,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
_LOGGER.debug('dump_rawdata: '+avr.protocol.dump_rawdata)
|
_LOGGER.debug('dump_rawdata: '+avr.protocol.dump_rawdata)
|
||||||
|
|
||||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, device.avr.close)
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, device.avr.close)
|
||||||
yield from async_add_devices([device])
|
async_add_devices([device])
|
||||||
|
|
||||||
|
|
||||||
class AnthemAVR(MediaPlayerDevice):
|
class AnthemAVR(MediaPlayerDevice):
|
||||||
|
@ -85,7 +85,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
players = yield from lms.create_players()
|
players = yield from lms.create_players()
|
||||||
yield from async_add_devices(players)
|
async_add_devices(players)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
config[CONF_ATTRS]
|
config[CONF_ATTRS]
|
||||||
)
|
)
|
||||||
|
|
||||||
yield from async_add_devices([player])
|
async_add_devices([player])
|
||||||
|
|
||||||
|
|
||||||
def validate_config(config):
|
def validate_config(config):
|
||||||
|
@ -18,7 +18,6 @@ from homeassistant.helpers.entity import Entity
|
|||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
|
|
||||||
DOMAIN = 'scene'
|
DOMAIN = 'scene'
|
||||||
DEPENDENCIES = ['group']
|
|
||||||
STATE = 'scening'
|
STATE = 'scening'
|
||||||
|
|
||||||
CONF_ENTITIES = "entities"
|
CONF_ENTITIES = "entities"
|
||||||
|
@ -13,7 +13,6 @@ from homeassistant.const import (
|
|||||||
from homeassistant.core import State
|
from homeassistant.core import State
|
||||||
from homeassistant.helpers.state import async_reproduce_state
|
from homeassistant.helpers.state import async_reproduce_state
|
||||||
|
|
||||||
DEPENDENCIES = ['group']
|
|
||||||
STATE = 'scening'
|
STATE = 'scening'
|
||||||
|
|
||||||
CONF_ENTITIES = "entities"
|
CONF_ENTITIES = "entities"
|
||||||
@ -29,7 +28,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
if not isinstance(scene_config, list):
|
if not isinstance(scene_config, list):
|
||||||
scene_config = [scene_config]
|
scene_config = [scene_config]
|
||||||
|
|
||||||
yield from async_add_devices(HomeAssistantScene(
|
async_add_devices(HomeAssistantScene(
|
||||||
hass, _process_config(scene)) for scene in scene_config)
|
hass, _process_config(scene)) for scene in scene_config)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ from homeassistant.helpers.script import Script
|
|||||||
DOMAIN = "script"
|
DOMAIN = "script"
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
GROUP_NAME_ALL_SCRIPTS = 'all scripts'
|
GROUP_NAME_ALL_SCRIPTS = 'all scripts'
|
||||||
DEPENDENCIES = ["group"]
|
|
||||||
|
|
||||||
CONF_SEQUENCE = "sequence"
|
CONF_SEQUENCE = "sequence"
|
||||||
|
|
||||||
@ -130,6 +129,7 @@ def async_setup(hass, config):
|
|||||||
schema=SCRIPT_TURN_ONOFF_SCHEMA)
|
schema=SCRIPT_TURN_ONOFF_SCHEMA)
|
||||||
hass.services.async_register(DOMAIN, SERVICE_TOGGLE, toggle_service,
|
hass.services.async_register(DOMAIN, SERVICE_TOGGLE, toggle_service,
|
||||||
schema=SCRIPT_TURN_ONOFF_SCHEMA)
|
schema=SCRIPT_TURN_ONOFF_SCHEMA)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
|
|
||||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, remove_logger)
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, remove_logger)
|
||||||
|
|
||||||
yield from async_add_devices([entity])
|
async_add_devices([entity])
|
||||||
|
|
||||||
|
|
||||||
class APICount(Entity):
|
class APICount(Entity):
|
||||||
|
@ -49,7 +49,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
else:
|
else:
|
||||||
resolver = config.get(CONF_RESOLVER)
|
resolver = config.get(CONF_RESOLVER)
|
||||||
|
|
||||||
yield from async_add_devices([WanIpSensor(
|
async_add_devices([WanIpSensor(
|
||||||
hass, hostname, resolver, ipv6)], True)
|
hass, hostname, resolver, ipv6)], True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
DerivativeDSMREntity('Hourly Gas Consumption', gas_obis),
|
DerivativeDSMREntity('Hourly Gas Consumption', gas_obis),
|
||||||
]
|
]
|
||||||
|
|
||||||
yield from async_add_devices(devices)
|
async_add_devices(devices)
|
||||||
|
|
||||||
def update_entities_telegram(telegram):
|
def update_entities_telegram(telegram):
|
||||||
"""Update entities with latests telegram & trigger state update."""
|
"""Update entities with latests telegram & trigger state update."""
|
||||||
|
@ -34,7 +34,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
hass.data[DATA_EVL])
|
hass.data[DATA_EVL])
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
|
|
||||||
yield from async_add_devices(devices)
|
async_add_devices(devices)
|
||||||
|
|
||||||
|
|
||||||
class EnvisalinkSensor(EnvisalinkDevice, Entity):
|
class EnvisalinkSensor(EnvisalinkDevice, Entity):
|
||||||
|
@ -61,7 +61,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
sensor_type = config.get(CONF_TYPE)
|
sensor_type = config.get(CONF_TYPE)
|
||||||
round_digits = config.get(CONF_ROUND_DIGITS)
|
round_digits = config.get(CONF_ROUND_DIGITS)
|
||||||
|
|
||||||
yield from async_add_devices(
|
async_add_devices(
|
||||||
[MinMaxSensor(hass, entity_ids, name, sensor_type, round_digits)],
|
[MinMaxSensor(hass, entity_ids, name, sensor_type, round_digits)],
|
||||||
True)
|
True)
|
||||||
return True
|
return True
|
||||||
|
@ -33,7 +33,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
"""Set up the Moon sensor."""
|
"""Set up the Moon sensor."""
|
||||||
name = config.get(CONF_NAME)
|
name = config.get(CONF_NAME)
|
||||||
|
|
||||||
yield from async_add_devices([MoonSensor(name)], True)
|
async_add_devices([MoonSensor(name)], True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
yield from async_add_devices([MqttSensor(
|
async_add_devices([MqttSensor(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
config.get(CONF_STATE_TOPIC),
|
config.get(CONF_STATE_TOPIC),
|
||||||
config.get(CONF_QOS),
|
config.get(CONF_QOS),
|
||||||
|
@ -59,7 +59,7 @@ MQTT_PAYLOAD = vol.Schema(vol.All(json.loads, vol.Schema({
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup MQTT Sensor."""
|
"""Setup MQTT Sensor."""
|
||||||
yield from async_add_devices([MQTTRoomSensor(
|
async_add_devices([MQTTRoomSensor(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
config.get(CONF_STATE_TOPIC),
|
config.get(CONF_STATE_TOPIC),
|
||||||
config.get(CONF_DEVICE_ID),
|
config.get(CONF_DEVICE_ID),
|
||||||
|
@ -36,7 +36,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
minimum = config.get(CONF_MINIMUM)
|
minimum = config.get(CONF_MINIMUM)
|
||||||
maximum = config.get(CONF_MAXIMUM)
|
maximum = config.get(CONF_MAXIMUM)
|
||||||
|
|
||||||
yield from async_add_devices([RandomSensor(name, minimum, maximum)], True)
|
async_add_devices([RandomSensor(name, minimum, maximum)], True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ def devices_from_config(domain_config, hass=None):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Set up the Rflink platform."""
|
"""Set up the Rflink platform."""
|
||||||
yield from async_add_devices(devices_from_config(config, hass))
|
async_add_devices(devices_from_config(config, hass))
|
||||||
|
|
||||||
# Add new (unconfigured) devices to user desired group
|
# Add new (unconfigured) devices to user desired group
|
||||||
if config[CONF_NEW_DEVICES_GROUP]:
|
if config[CONF_NEW_DEVICES_GROUP]:
|
||||||
@ -91,7 +91,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
rflinksensor = partial(RflinkSensor, device_id, hass)
|
rflinksensor = partial(RflinkSensor, device_id, hass)
|
||||||
device = rflinksensor(event[EVENT_KEY_SENSOR], event[EVENT_KEY_UNIT])
|
device = rflinksensor(event[EVENT_KEY_SENSOR], event[EVENT_KEY_UNIT])
|
||||||
# Add device entity
|
# Add device entity
|
||||||
yield from async_add_devices([device])
|
async_add_devices([device])
|
||||||
|
|
||||||
# Register entity to listen to incoming rflink events
|
# Register entity to listen to incoming rflink events
|
||||||
hass.data[DATA_ENTITY_LOOKUP][
|
hass.data[DATA_ENTITY_LOOKUP][
|
||||||
@ -122,6 +122,11 @@ class RflinkSensor(RflinkDevice):
|
|||||||
"""Domain specific event handler."""
|
"""Domain specific event handler."""
|
||||||
self._state = event['value']
|
self._state = event['value']
|
||||||
|
|
||||||
|
@property
|
||||||
|
def entity_id(self):
|
||||||
|
"""Return entity id."""
|
||||||
|
return "sensor.{}".format(self.name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self):
|
||||||
"""Return measurement unit."""
|
"""Return measurement unit."""
|
||||||
|
@ -50,7 +50,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
name = config.get(CONF_NAME)
|
name = config.get(CONF_NAME)
|
||||||
sampling_size = config.get(CONF_SAMPLING_SIZE)
|
sampling_size = config.get(CONF_SAMPLING_SIZE)
|
||||||
|
|
||||||
yield from async_add_devices(
|
async_add_devices(
|
||||||
[StatisticsSensor(hass, entity_id, name, sampling_size)], True)
|
[StatisticsSensor(hass, entity_id, name, sampling_size)], True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
_LOGGER.error("No sensors added")
|
_LOGGER.error("No sensors added")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
yield from async_add_devices(sensors, True)
|
async_add_devices(sensors, True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
for variable in config[CONF_DISPLAY_OPTIONS]:
|
for variable in config[CONF_DISPLAY_OPTIONS]:
|
||||||
devices.append(TimeDateSensor(variable))
|
devices.append(TimeDateSensor(variable))
|
||||||
|
|
||||||
yield from async_add_devices(devices, True)
|
async_add_devices(devices, True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
name = config.get(CONF_NAME)
|
name = config.get(CONF_NAME)
|
||||||
time_zone = dt_util.get_time_zone(config.get(CONF_TIME_ZONE))
|
time_zone = dt_util.get_time_zone(config.get(CONF_TIME_ZONE))
|
||||||
|
|
||||||
yield from async_add_devices([WorldClockSensor(time_zone, name)], True)
|
async_add_devices([WorldClockSensor(time_zone, name)], True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
dev = []
|
dev = []
|
||||||
for sensor_type in config[CONF_MONITORED_CONDITIONS]:
|
for sensor_type in config[CONF_MONITORED_CONDITIONS]:
|
||||||
dev.append(YrSensor(sensor_type))
|
dev.append(YrSensor(sensor_type))
|
||||||
yield from async_add_devices(dev)
|
async_add_devices(dev)
|
||||||
|
|
||||||
weather = YrData(hass, coordinates, dev)
|
weather = YrData(hass, coordinates, dev)
|
||||||
# Update weather on the hour, spread seconds
|
# Update weather on the hour, spread seconds
|
||||||
|
@ -74,7 +74,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
if response is not None:
|
if response is not None:
|
||||||
yield from response.release()
|
yield from response.release()
|
||||||
|
|
||||||
yield from async_add_devices(
|
async_add_devices(
|
||||||
HookSmartHome(
|
HookSmartHome(
|
||||||
hass,
|
hass,
|
||||||
token,
|
token,
|
||||||
|
@ -43,7 +43,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
|
||||||
yield from async_add_devices([MqttSwitch(
|
async_add_devices([MqttSwitch(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
config.get(CONF_STATE_TOPIC),
|
config.get(CONF_STATE_TOPIC),
|
||||||
config.get(CONF_COMMAND_TOPIC),
|
config.get(CONF_COMMAND_TOPIC),
|
||||||
|
@ -72,7 +72,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
if req is not None:
|
if req is not None:
|
||||||
yield from req.release()
|
yield from req.release()
|
||||||
|
|
||||||
yield from async_add_devices(
|
async_add_devices(
|
||||||
[RestSwitch(hass, name, resource, body_on, body_off,
|
[RestSwitch(hass, name, resource, body_on, body_off,
|
||||||
is_on_template, timeout)])
|
is_on_template, timeout)])
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ def devices_from_config(domain_config, hass=None):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Set up the Rflink platform."""
|
"""Set up the Rflink platform."""
|
||||||
yield from async_add_devices(devices_from_config(config, hass))
|
async_add_devices(devices_from_config(config, hass))
|
||||||
|
|
||||||
|
|
||||||
class RflinkSwitch(SwitchableRflinkDevice, SwitchDevice):
|
class RflinkSwitch(SwitchableRflinkDevice, SwitchDevice):
|
||||||
|
@ -70,7 +70,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
_LOGGER.error("No switches added")
|
_LOGGER.error("No switches added")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
yield from async_add_devices(switches, True)
|
async_add_devices(switches, True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
device = hass.data[DATA_ZWAVE_DICT].pop(
|
device = hass.data[DATA_ZWAVE_DICT].pop(
|
||||||
discovery_info[const.DISCOVERY_DEVICE])
|
discovery_info[const.DISCOVERY_DEVICE])
|
||||||
if device:
|
if device:
|
||||||
yield from async_add_devices([device])
|
async_add_devices([device])
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -10,23 +10,27 @@ import sys
|
|||||||
from typing import Any, List, Tuple # NOQA
|
from typing import Any, List, Tuple # NOQA
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
from voluptuous.humanize import humanize_error
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, CONF_PACKAGES, CONF_UNIT_SYSTEM,
|
CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, CONF_PACKAGES, CONF_UNIT_SYSTEM,
|
||||||
CONF_TIME_ZONE, CONF_ELEVATION, CONF_UNIT_SYSTEM_METRIC,
|
CONF_TIME_ZONE, CONF_ELEVATION, CONF_UNIT_SYSTEM_METRIC,
|
||||||
CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS,
|
CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS,
|
||||||
__version__, CONF_CUSTOMIZE, CONF_CUSTOMIZE_DOMAIN, CONF_CUSTOMIZE_GLOB)
|
__version__, CONF_CUSTOMIZE, CONF_CUSTOMIZE_DOMAIN, CONF_CUSTOMIZE_GLOB)
|
||||||
from homeassistant.core import DOMAIN as CONF_CORE
|
from homeassistant.core import callback, DOMAIN as CONF_CORE
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.loader import get_component
|
from homeassistant.loader import get_component, get_platform
|
||||||
from homeassistant.util.yaml import load_yaml
|
from homeassistant.util.yaml import load_yaml
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.util import dt as date_util, location as loc_util
|
from homeassistant.util import dt as date_util, location as loc_util
|
||||||
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM
|
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM
|
||||||
from homeassistant.helpers.entity_values import EntityValues
|
from homeassistant.helpers.entity_values import EntityValues
|
||||||
|
from homeassistant.helpers import config_per_platform, extract_domain_configs
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
DATA_PERSISTENT_ERRORS = 'bootstrap_persistent_errors'
|
||||||
|
HA_COMPONENT_URL = '[{}](https://home-assistant.io/components/{}/)'
|
||||||
YAML_CONFIG_FILE = 'configuration.yaml'
|
YAML_CONFIG_FILE = 'configuration.yaml'
|
||||||
VERSION_FILE = '.HA_VERSION'
|
VERSION_FILE = '.HA_VERSION'
|
||||||
CONFIG_DIR_NAME = '.homeassistant'
|
CONFIG_DIR_NAME = '.homeassistant'
|
||||||
@ -274,6 +278,35 @@ def process_ha_config_upgrade(hass):
|
|||||||
outp.write(__version__)
|
outp.write(__version__)
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_log_exception(ex, domain, config, hass):
|
||||||
|
"""Generate log exception for config validation.
|
||||||
|
|
||||||
|
This method must be run in the event loop.
|
||||||
|
"""
|
||||||
|
message = 'Invalid config for [{}]: '.format(domain)
|
||||||
|
if hass is not None:
|
||||||
|
async_notify_setup_error(hass, domain, True)
|
||||||
|
|
||||||
|
if 'extra keys not allowed' in ex.error_message:
|
||||||
|
message += '[{}] is an invalid option for [{}]. Check: {}->{}.'\
|
||||||
|
.format(ex.path[-1], domain, domain,
|
||||||
|
'->'.join(str(m) for m in ex.path))
|
||||||
|
else:
|
||||||
|
message += '{}.'.format(humanize_error(config, ex))
|
||||||
|
|
||||||
|
domain_config = config.get(domain, config)
|
||||||
|
message += " (See {}, line {}). ".format(
|
||||||
|
getattr(domain_config, '__config_file__', '?'),
|
||||||
|
getattr(domain_config, '__line__', '?'))
|
||||||
|
|
||||||
|
if domain != 'homeassistant':
|
||||||
|
message += ('Please check the docs at '
|
||||||
|
'https://home-assistant.io/components/{}/'.format(domain))
|
||||||
|
|
||||||
|
_LOGGER.error(message)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_process_ha_core_config(hass, config):
|
def async_process_ha_core_config(hass, config):
|
||||||
"""Process the [homeassistant] section from the config.
|
"""Process the [homeassistant] section from the config.
|
||||||
@ -483,6 +516,67 @@ def merge_packages_config(config, packages):
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_process_component_config(hass, config, domain):
|
||||||
|
"""Check component config and return processed config.
|
||||||
|
|
||||||
|
Raise a vol.Invalid exception on error.
|
||||||
|
|
||||||
|
This method must be run in the event loop.
|
||||||
|
"""
|
||||||
|
component = get_component(domain)
|
||||||
|
|
||||||
|
if hasattr(component, 'CONFIG_SCHEMA'):
|
||||||
|
try:
|
||||||
|
config = component.CONFIG_SCHEMA(config)
|
||||||
|
except vol.Invalid as ex:
|
||||||
|
async_log_exception(ex, domain, config, hass)
|
||||||
|
return None
|
||||||
|
|
||||||
|
elif hasattr(component, 'PLATFORM_SCHEMA'):
|
||||||
|
platforms = []
|
||||||
|
for p_name, p_config in config_per_platform(config, domain):
|
||||||
|
# Validate component specific platform schema
|
||||||
|
try:
|
||||||
|
p_validated = component.PLATFORM_SCHEMA(p_config)
|
||||||
|
except vol.Invalid as ex:
|
||||||
|
async_log_exception(ex, domain, config, hass)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Not all platform components follow same pattern for platforms
|
||||||
|
# So if p_name is None we are not going to validate platform
|
||||||
|
# (the automation component is one of them)
|
||||||
|
if p_name is None:
|
||||||
|
platforms.append(p_validated)
|
||||||
|
continue
|
||||||
|
|
||||||
|
platform = get_platform(domain, p_name)
|
||||||
|
|
||||||
|
if platform is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Validate platform specific schema
|
||||||
|
if hasattr(platform, 'PLATFORM_SCHEMA'):
|
||||||
|
# pylint: disable=no-member
|
||||||
|
try:
|
||||||
|
p_validated = platform.PLATFORM_SCHEMA(p_validated)
|
||||||
|
except vol.Invalid as ex:
|
||||||
|
async_log_exception(ex, '{}.{}'.format(domain, p_name),
|
||||||
|
p_validated, hass)
|
||||||
|
continue
|
||||||
|
|
||||||
|
platforms.append(p_validated)
|
||||||
|
|
||||||
|
# Create a copy of the configuration with all config for current
|
||||||
|
# component removed and add validated config back in.
|
||||||
|
filter_keys = extract_domain_configs(config, domain)
|
||||||
|
config = {key: value for key, value in config.items()
|
||||||
|
if key not in filter_keys}
|
||||||
|
config[domain] = platforms
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_check_ha_config_file(hass):
|
def async_check_ha_config_file(hass):
|
||||||
"""Check if HA config file valid.
|
"""Check if HA config file valid.
|
||||||
@ -501,3 +595,25 @@ def async_check_ha_config_file(hass):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
return re.sub(r'\033\[[^m]*m', '', str(stdout_data, 'utf-8'))
|
return re.sub(r'\033\[[^m]*m', '', str(stdout_data, 'utf-8'))
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_notify_setup_error(hass, component, link=False):
|
||||||
|
"""Print a persistent notification.
|
||||||
|
|
||||||
|
This method must be run in the event loop.
|
||||||
|
"""
|
||||||
|
from homeassistant.components import persistent_notification
|
||||||
|
|
||||||
|
errors = hass.data.get(DATA_PERSISTENT_ERRORS)
|
||||||
|
|
||||||
|
if errors is None:
|
||||||
|
errors = hass.data[DATA_PERSISTENT_ERRORS] = {}
|
||||||
|
|
||||||
|
errors[component] = errors.get(component) or link
|
||||||
|
_lst = [HA_COMPONENT_URL.format(name.replace('_', '-'), name)
|
||||||
|
if link else name for name, link in errors.items()]
|
||||||
|
message = ('The following components and platforms could not be set up:\n'
|
||||||
|
'* ' + '\n* '.join(list(_lst)) + '\nPlease check your config')
|
||||||
|
persistent_notification.async_create(
|
||||||
|
hass, message, 'Invalid config', 'invalid_config')
|
||||||
|
@ -122,6 +122,7 @@ class HomeAssistant(object):
|
|||||||
self.loop.set_default_executor(self.executor)
|
self.loop.set_default_executor(self.executor)
|
||||||
self.loop.set_exception_handler(async_loop_exception_handler)
|
self.loop.set_exception_handler(async_loop_exception_handler)
|
||||||
self._pending_tasks = []
|
self._pending_tasks = []
|
||||||
|
self._track_task = False
|
||||||
self.bus = EventBus(self)
|
self.bus = EventBus(self)
|
||||||
self.services = ServiceRegistry(self)
|
self.services = ServiceRegistry(self)
|
||||||
self.states = StateMachine(self.bus, self.loop)
|
self.states = StateMachine(self.bus, self.loop)
|
||||||
@ -178,28 +179,7 @@ class HomeAssistant(object):
|
|||||||
self.loop.call_soon_threadsafe(self.async_add_job, target, *args)
|
self.loop.call_soon_threadsafe(self.async_add_job, target, *args)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_add_job(self, target: Callable[..., None], *args: Any) -> None:
|
def async_add_job(self, target: Callable[..., None], *args: Any) -> None:
|
||||||
"""Add a job from within the eventloop.
|
|
||||||
|
|
||||||
This method must be run in the event loop.
|
|
||||||
|
|
||||||
target: target to call.
|
|
||||||
args: parameters for method to call.
|
|
||||||
"""
|
|
||||||
if asyncio.iscoroutine(target):
|
|
||||||
self.loop.create_task(target)
|
|
||||||
elif is_callback(target):
|
|
||||||
self.loop.call_soon(target, *args)
|
|
||||||
elif asyncio.iscoroutinefunction(target):
|
|
||||||
self.loop.create_task(target(*args))
|
|
||||||
else:
|
|
||||||
self.loop.run_in_executor(None, target, *args)
|
|
||||||
|
|
||||||
async_add_job = _async_add_job
|
|
||||||
|
|
||||||
@callback
|
|
||||||
def _async_add_job_tracking(self, target: Callable[..., None],
|
|
||||||
*args: Any) -> None:
|
|
||||||
"""Add a job from within the eventloop.
|
"""Add a job from within the eventloop.
|
||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
@ -219,19 +199,21 @@ class HomeAssistant(object):
|
|||||||
task = self.loop.run_in_executor(None, target, *args)
|
task = self.loop.run_in_executor(None, target, *args)
|
||||||
|
|
||||||
# if a task is sheduled
|
# if a task is sheduled
|
||||||
if task is not None:
|
if self._track_task and task is not None:
|
||||||
self._pending_tasks.append(task)
|
self._pending_tasks.append(task)
|
||||||
|
|
||||||
|
return task
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_track_tasks(self):
|
def async_track_tasks(self):
|
||||||
"""Track tasks so you can wait for all tasks to be done."""
|
"""Track tasks so you can wait for all tasks to be done."""
|
||||||
self.async_add_job = self._async_add_job_tracking
|
self._track_task = True
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_stop_track_tasks(self):
|
def async_stop_track_tasks(self):
|
||||||
"""Track tasks so you can wait for all tasks to be done."""
|
"""Track tasks so you can wait for all tasks to be done."""
|
||||||
yield from self.async_block_till_done()
|
yield from self.async_block_till_done()
|
||||||
self.async_add_job = self._async_add_job
|
self._track_task = False
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_run_job(self, target: Callable[..., None], *args: Any) -> None:
|
def async_run_job(self, target: Callable[..., None], *args: Any) -> None:
|
||||||
|
@ -63,20 +63,8 @@ def async_discover(hass, service, discovered=None, component=None,
|
|||||||
'Cannot discover the {} component.'.format(component))
|
'Cannot discover the {} component.'.format(component))
|
||||||
|
|
||||||
if component is not None and component not in hass.config.components:
|
if component is not None and component not in hass.config.components:
|
||||||
did_lock = False
|
yield from bootstrap.async_setup_component(
|
||||||
setup_lock = hass.data.get('setup_lock')
|
hass, component, hass_config)
|
||||||
if setup_lock and setup_lock.locked():
|
|
||||||
did_lock = True
|
|
||||||
yield from setup_lock.acquire()
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Could have been loaded while waiting for lock.
|
|
||||||
if component not in hass.config.components:
|
|
||||||
yield from bootstrap.async_setup_component(hass, component,
|
|
||||||
hass_config)
|
|
||||||
finally:
|
|
||||||
if did_lock:
|
|
||||||
setup_lock.release()
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
ATTR_SERVICE: service
|
ATTR_SERVICE: service
|
||||||
@ -160,22 +148,11 @@ def async_load_platform(hass, component, platform, discovered=None,
|
|||||||
raise HomeAssistantError(
|
raise HomeAssistantError(
|
||||||
'Cannot discover the {} component.'.format(component))
|
'Cannot discover the {} component.'.format(component))
|
||||||
|
|
||||||
did_lock = False
|
|
||||||
setup_lock = hass.data.get('setup_lock')
|
|
||||||
if setup_lock and setup_lock.locked():
|
|
||||||
did_lock = True
|
|
||||||
yield from setup_lock.acquire()
|
|
||||||
|
|
||||||
setup_success = True
|
setup_success = True
|
||||||
|
|
||||||
try:
|
|
||||||
# Could have been loaded while waiting for lock.
|
|
||||||
if component not in hass.config.components:
|
if component not in hass.config.components:
|
||||||
setup_success = yield from bootstrap.async_setup_component(
|
setup_success = yield from bootstrap.async_setup_component(
|
||||||
hass, component, hass_config)
|
hass, component, hass_config)
|
||||||
finally:
|
|
||||||
if did_lock:
|
|
||||||
setup_lock.release()
|
|
||||||
|
|
||||||
# No need to fire event if we could not setup component
|
# No need to fire event if we could not setup component
|
||||||
if not setup_success:
|
if not setup_success:
|
||||||
|
@ -3,8 +3,7 @@ import asyncio
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from homeassistant import config as conf_util
|
from homeassistant import config as conf_util
|
||||||
from homeassistant.bootstrap import (
|
from homeassistant.bootstrap import async_prepare_setup_platform
|
||||||
async_prepare_setup_platform, async_prepare_setup_component)
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, CONF_SCAN_INTERVAL, CONF_ENTITY_NAMESPACE,
|
ATTR_ENTITY_ID, CONF_SCAN_INTERVAL, CONF_ENTITY_NAMESPACE,
|
||||||
DEVICE_DEFAULT_NAME)
|
DEVICE_DEFAULT_NAME)
|
||||||
@ -49,12 +48,9 @@ class EntityComponent(object):
|
|||||||
def setup(self, config):
|
def setup(self, config):
|
||||||
"""Set up a full entity component.
|
"""Set up a full entity component.
|
||||||
|
|
||||||
Loads the platforms from the config and will listen for supported
|
This doesn't block the executor to protect from deadlocks.
|
||||||
discovered platforms.
|
|
||||||
"""
|
"""
|
||||||
run_coroutine_threadsafe(
|
self.hass.add_job(self.async_setup(config))
|
||||||
self.async_setup(config), self.hass.loop
|
|
||||||
).result()
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup(self, config):
|
def async_setup(self, config):
|
||||||
@ -143,14 +139,16 @@ class EntityComponent(object):
|
|||||||
if getattr(platform, 'async_setup_platform', None):
|
if getattr(platform, 'async_setup_platform', None):
|
||||||
yield from platform.async_setup_platform(
|
yield from platform.async_setup_platform(
|
||||||
self.hass, platform_config,
|
self.hass, platform_config,
|
||||||
entity_platform.async_add_entities, discovery_info
|
entity_platform.async_schedule_add_entities, discovery_info
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
yield from self.hass.loop.run_in_executor(
|
yield from self.hass.loop.run_in_executor(
|
||||||
None, platform.setup_platform, self.hass, platform_config,
|
None, platform.setup_platform, self.hass, platform_config,
|
||||||
entity_platform.add_entities, discovery_info
|
entity_platform.schedule_add_entities, discovery_info
|
||||||
)
|
)
|
||||||
|
|
||||||
|
yield from entity_platform.async_block_entities_done()
|
||||||
|
|
||||||
self.hass.config.components.add(
|
self.hass.config.components.add(
|
||||||
'{}.{}'.format(self.domain, platform_type))
|
'{}.{}'.format(self.domain, platform_type))
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
@ -275,7 +273,7 @@ class EntityComponent(object):
|
|||||||
self.logger.error(err)
|
self.logger.error(err)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
conf = yield from async_prepare_setup_component(
|
conf = conf_util.async_process_component_config(
|
||||||
self.hass, conf, self.domain)
|
self.hass, conf, self.domain)
|
||||||
|
|
||||||
if conf is None:
|
if conf is None:
|
||||||
@ -295,9 +293,40 @@ class EntityPlatform(object):
|
|||||||
self.scan_interval = scan_interval
|
self.scan_interval = scan_interval
|
||||||
self.entity_namespace = entity_namespace
|
self.entity_namespace = entity_namespace
|
||||||
self.platform_entities = []
|
self.platform_entities = []
|
||||||
|
self._tasks = []
|
||||||
self._async_unsub_polling = None
|
self._async_unsub_polling = None
|
||||||
self._process_updates = asyncio.Lock(loop=component.hass.loop)
|
self._process_updates = asyncio.Lock(loop=component.hass.loop)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_block_entities_done(self):
|
||||||
|
"""Wait until all entities add to hass."""
|
||||||
|
if self._tasks:
|
||||||
|
pending = [task for task in self._tasks if not task.done()]
|
||||||
|
self._tasks.clear()
|
||||||
|
|
||||||
|
if pending:
|
||||||
|
yield from asyncio.wait(pending, loop=self.component.hass.loop)
|
||||||
|
|
||||||
|
def schedule_add_entities(self, new_entities, update_before_add=False):
|
||||||
|
"""Add entities for a single platform."""
|
||||||
|
if update_before_add:
|
||||||
|
for entity in new_entities:
|
||||||
|
entity.update()
|
||||||
|
|
||||||
|
run_callback_threadsafe(
|
||||||
|
self.component.hass.loop,
|
||||||
|
self.async_schedule_add_entities, list(new_entities), False
|
||||||
|
).result()
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_schedule_add_entities(self, new_entities,
|
||||||
|
update_before_add=False):
|
||||||
|
"""Add entities for a single platform async."""
|
||||||
|
self._tasks.append(self.component.hass.async_add_job(
|
||||||
|
self.async_add_entities(
|
||||||
|
new_entities, update_before_add=update_before_add)
|
||||||
|
))
|
||||||
|
|
||||||
def add_entities(self, new_entities, update_before_add=False):
|
def add_entities(self, new_entities, update_before_add=False):
|
||||||
"""Add entities for a single platform."""
|
"""Add entities for a single platform."""
|
||||||
if update_before_add:
|
if update_before_add:
|
||||||
@ -306,8 +335,7 @@ class EntityPlatform(object):
|
|||||||
|
|
||||||
run_coroutine_threadsafe(
|
run_coroutine_threadsafe(
|
||||||
self.async_add_entities(list(new_entities), False),
|
self.async_add_entities(list(new_entities), False),
|
||||||
self.component.hass.loop
|
self.component.hass.loop).result()
|
||||||
).result()
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_add_entities(self, new_entities, update_before_add=False):
|
def async_add_entities(self, new_entities, update_before_add=False):
|
||||||
@ -319,8 +347,16 @@ class EntityPlatform(object):
|
|||||||
if not new_entities:
|
if not new_entities:
|
||||||
return
|
return
|
||||||
|
|
||||||
tasks = [self._async_process_entity(entity, update_before_add)
|
@asyncio.coroutine
|
||||||
for entity in new_entities]
|
def async_process_entity(new_entity):
|
||||||
|
"""Add entities to StateMachine."""
|
||||||
|
ret = yield from self.component.async_add_entity(
|
||||||
|
new_entity, self, update_before_add=update_before_add
|
||||||
|
)
|
||||||
|
if ret:
|
||||||
|
self.platform_entities.append(new_entity)
|
||||||
|
|
||||||
|
tasks = [async_process_entity(entity) for entity in new_entities]
|
||||||
|
|
||||||
yield from asyncio.wait(tasks, loop=self.component.hass.loop)
|
yield from asyncio.wait(tasks, loop=self.component.hass.loop)
|
||||||
yield from self.component.async_update_group()
|
yield from self.component.async_update_group()
|
||||||
@ -334,15 +370,6 @@ class EntityPlatform(object):
|
|||||||
self.component.hass, self._update_entity_states, self.scan_interval
|
self.component.hass, self._update_entity_states, self.scan_interval
|
||||||
)
|
)
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def _async_process_entity(self, new_entity, update_before_add):
|
|
||||||
"""Add entities to StateMachine."""
|
|
||||||
ret = yield from self.component.async_add_entity(
|
|
||||||
new_entity, self, update_before_add=update_before_add
|
|
||||||
)
|
|
||||||
if ret:
|
|
||||||
self.platform_entities.append(new_entity)
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_reset(self):
|
def async_reset(self):
|
||||||
"""Remove all entities and reset data.
|
"""Remove all entities and reset data.
|
||||||
|
@ -170,41 +170,6 @@ def get_component(comp_name) -> Optional[ModuleType]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def load_order_components(components: Sequence[str]) -> OrderedSet:
|
|
||||||
"""Take in a list of components we want to load.
|
|
||||||
|
|
||||||
- filters out components we cannot load
|
|
||||||
- filters out components that have invalid/circular dependencies
|
|
||||||
- Will make sure the recorder component is loaded first
|
|
||||||
- Will ensure that all components that do not directly depend on
|
|
||||||
the group component will be loaded before the group component.
|
|
||||||
- returns an OrderedSet load order.
|
|
||||||
- Makes sure MQTT eventstream is available for publish before
|
|
||||||
components start updating states.
|
|
||||||
|
|
||||||
Async friendly.
|
|
||||||
"""
|
|
||||||
_check_prepared()
|
|
||||||
|
|
||||||
load_order = OrderedSet()
|
|
||||||
|
|
||||||
# Sort the list of modules on if they depend on group component or not.
|
|
||||||
# Components that do not depend on the group usually set up states.
|
|
||||||
# Components that depend on group usually use states in their setup.
|
|
||||||
for comp_load_order in sorted((load_order_component(component)
|
|
||||||
for component in components),
|
|
||||||
key=lambda order: 'group' in order):
|
|
||||||
load_order.update(comp_load_order)
|
|
||||||
|
|
||||||
# Push some to first place in load order
|
|
||||||
for comp in ('mqtt_eventstream', 'mqtt', 'recorder',
|
|
||||||
'introduction', 'logger'):
|
|
||||||
if comp in load_order:
|
|
||||||
load_order.promote(comp)
|
|
||||||
|
|
||||||
return load_order
|
|
||||||
|
|
||||||
|
|
||||||
def load_order_component(comp_name: str) -> OrderedSet:
|
def load_order_component(comp_name: str) -> OrderedSet:
|
||||||
"""Return an OrderedSet of components in the correct order of loading.
|
"""Return an OrderedSet of components in the correct order of loading.
|
||||||
|
|
||||||
|
@ -26,8 +26,8 @@ MOCKS = {
|
|||||||
'load*': ("homeassistant.config.load_yaml", yaml.load_yaml),
|
'load*': ("homeassistant.config.load_yaml", yaml.load_yaml),
|
||||||
'get': ("homeassistant.loader.get_component", loader.get_component),
|
'get': ("homeassistant.loader.get_component", loader.get_component),
|
||||||
'secrets': ("homeassistant.util.yaml._secret_yaml", yaml._secret_yaml),
|
'secrets': ("homeassistant.util.yaml._secret_yaml", yaml._secret_yaml),
|
||||||
'except': ("homeassistant.bootstrap.async_log_exception",
|
'except': ("homeassistant.config.async_log_exception",
|
||||||
bootstrap.async_log_exception),
|
config_util.async_log_exception),
|
||||||
'package_error': ("homeassistant.config._log_pkg_error",
|
'package_error': ("homeassistant.config._log_pkg_error",
|
||||||
config_util._log_pkg_error),
|
config_util._log_pkg_error),
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ def check(config_path):
|
|||||||
|
|
||||||
def mock_except(ex, domain, config, # pylint: disable=unused-variable
|
def mock_except(ex, domain, config, # pylint: disable=unused-variable
|
||||||
hass=None):
|
hass=None):
|
||||||
"""Mock bootstrap.log_exception."""
|
"""Mock config.log_exception."""
|
||||||
MOCKS['except'][1](ex, domain, config, hass)
|
MOCKS['except'][1](ex, domain, config, hass)
|
||||||
res['except'][domain] = config.get(domain, config)
|
res['except'][domain] = config.get(domain, config)
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ from contextlib import contextmanager
|
|||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
|
||||||
from homeassistant import core as ha, loader
|
from homeassistant import core as ha, loader
|
||||||
from homeassistant.bootstrap import (
|
from homeassistant.bootstrap import setup_component, DATA_SETUP
|
||||||
setup_component, async_prepare_setup_component)
|
from homeassistant.config import async_process_component_config
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.entity import ToggleEntity
|
from homeassistant.helpers.entity import ToggleEntity
|
||||||
from homeassistant.helpers.restore_state import DATA_RESTORE_CACHE
|
from homeassistant.helpers.restore_state import DATA_RESTORE_CACHE
|
||||||
@ -93,13 +93,16 @@ def async_test_home_assistant(loop):
|
|||||||
|
|
||||||
hass = ha.HomeAssistant(loop)
|
hass = ha.HomeAssistant(loop)
|
||||||
|
|
||||||
|
orig_async_add_job = hass.async_add_job
|
||||||
|
|
||||||
def async_add_job(target, *args):
|
def async_add_job(target, *args):
|
||||||
"""Add a magic mock."""
|
"""Add a magic mock."""
|
||||||
if isinstance(target, MagicMock):
|
if isinstance(target, MagicMock):
|
||||||
return
|
return
|
||||||
hass._async_add_job_tracking(target, *args)
|
return orig_async_add_job(target, *args)
|
||||||
|
|
||||||
hass.async_add_job = async_add_job
|
hass.async_add_job = async_add_job
|
||||||
|
hass.async_track_tasks()
|
||||||
|
|
||||||
hass.config.location_name = 'test home'
|
hass.config.location_name = 'test home'
|
||||||
hass.config.config_dir = get_test_config_dir()
|
hass.config.config_dir = get_test_config_dir()
|
||||||
@ -230,7 +233,7 @@ def mock_state_change_event(hass, new_state, old_state=None):
|
|||||||
def mock_http_component(hass, api_password=None):
|
def mock_http_component(hass, api_password=None):
|
||||||
"""Mock the HTTP component."""
|
"""Mock the HTTP component."""
|
||||||
hass.http = MagicMock(api_password=api_password)
|
hass.http = MagicMock(api_password=api_password)
|
||||||
hass.config.components.add('http')
|
mock_component(hass, 'http')
|
||||||
hass.http.views = {}
|
hass.http.views = {}
|
||||||
|
|
||||||
def mock_register_view(view):
|
def mock_register_view(view):
|
||||||
@ -268,6 +271,19 @@ def mock_mqtt_component(hass):
|
|||||||
return mock_mqtt
|
return mock_mqtt
|
||||||
|
|
||||||
|
|
||||||
|
def mock_component(hass, component):
|
||||||
|
"""Mock a component is setup."""
|
||||||
|
setup_tasks = hass.data.get(DATA_SETUP)
|
||||||
|
if setup_tasks is None:
|
||||||
|
setup_tasks = hass.data[DATA_SETUP] = {}
|
||||||
|
|
||||||
|
if component not in setup_tasks:
|
||||||
|
AssertionError("Component {} is already setup".format(component))
|
||||||
|
|
||||||
|
hass.config.components.add(component)
|
||||||
|
setup_tasks[component] = asyncio.Task(mock_coro(True), loop=hass.loop)
|
||||||
|
|
||||||
|
|
||||||
class MockModule(object):
|
class MockModule(object):
|
||||||
"""Representation of a fake module."""
|
"""Representation of a fake module."""
|
||||||
|
|
||||||
@ -439,10 +455,10 @@ def assert_setup_component(count, domain=None):
|
|||||||
"""
|
"""
|
||||||
config = {}
|
config = {}
|
||||||
|
|
||||||
@asyncio.coroutine
|
@ha.callback
|
||||||
def mock_psc(hass, config_input, domain):
|
def mock_psc(hass, config_input, domain):
|
||||||
"""Mock the prepare_setup_component to capture config."""
|
"""Mock the prepare_setup_component to capture config."""
|
||||||
res = yield from async_prepare_setup_component(
|
res = async_process_component_config(
|
||||||
hass, config_input, domain)
|
hass, config_input, domain)
|
||||||
config[domain] = None if res is None else res.get(domain)
|
config[domain] = None if res is None else res.get(domain)
|
||||||
_LOGGER.debug('Configuration for %s, Validated: %s, Original %s',
|
_LOGGER.debug('Configuration for %s, Validated: %s, Original %s',
|
||||||
@ -450,7 +466,7 @@ def assert_setup_component(count, domain=None):
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
assert isinstance(config, dict)
|
assert isinstance(config, dict)
|
||||||
with patch('homeassistant.bootstrap.async_prepare_setup_component',
|
with patch('homeassistant.config.async_process_component_config',
|
||||||
mock_psc):
|
mock_psc):
|
||||||
yield config
|
yield config
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_fail_setup_without_state_topic(self):
|
def test_fail_setup_without_state_topic(self):
|
||||||
"""Test for failing with no state topic."""
|
"""Test for failing with no state topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(0) as config:
|
with assert_setup_component(0) as config:
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
@ -42,7 +41,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_fail_setup_without_command_topic(self):
|
def test_fail_setup_without_command_topic(self):
|
||||||
"""Test failing with no command topic."""
|
"""Test failing with no command topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(0):
|
with assert_setup_component(0):
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
@ -53,7 +51,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_update_state_via_state_topic(self):
|
def test_update_state_via_state_topic(self):
|
||||||
"""Test updating with via state topic."""
|
"""Test updating with via state topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -77,7 +74,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_ignore_update_state_if_unknown_via_state_topic(self):
|
def test_ignore_update_state_if_unknown_via_state_topic(self):
|
||||||
"""Test ignoring updates via state topic."""
|
"""Test ignoring updates via state topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -98,7 +94,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_arm_home_publishes_mqtt(self):
|
def test_arm_home_publishes_mqtt(self):
|
||||||
"""Test publishing of MQTT messages while armed."""
|
"""Test publishing of MQTT messages while armed."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -115,7 +110,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_arm_home_not_publishes_mqtt_with_invalid_code(self):
|
def test_arm_home_not_publishes_mqtt_with_invalid_code(self):
|
||||||
"""Test not publishing of MQTT messages with invalid code."""
|
"""Test not publishing of MQTT messages with invalid code."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -133,7 +127,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_arm_away_publishes_mqtt(self):
|
def test_arm_away_publishes_mqtt(self):
|
||||||
"""Test publishing of MQTT messages while armed."""
|
"""Test publishing of MQTT messages while armed."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -150,7 +143,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_arm_away_not_publishes_mqtt_with_invalid_code(self):
|
def test_arm_away_not_publishes_mqtt_with_invalid_code(self):
|
||||||
"""Test not publishing of MQTT messages with invalid code."""
|
"""Test not publishing of MQTT messages with invalid code."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -168,7 +160,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_disarm_publishes_mqtt(self):
|
def test_disarm_publishes_mqtt(self):
|
||||||
"""Test publishing of MQTT messages while disarmed."""
|
"""Test publishing of MQTT messages while disarmed."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -185,7 +176,6 @@ class TestAlarmControlPanelMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_disarm_not_publishes_mqtt_with_invalid_code(self):
|
def test_disarm_not_publishes_mqtt_with_invalid_code(self):
|
||||||
"""Test not publishing of MQTT messages with invalid code."""
|
"""Test not publishing of MQTT messages with invalid code."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
assert setup_component(self.hass, alarm_control_panel.DOMAIN, {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
|
@ -5,7 +5,7 @@ from homeassistant.core import callback
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -15,7 +15,7 @@ class TestAutomationEvent(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('group')
|
mock_component(self.hass, 'group')
|
||||||
self.calls = []
|
self.calls = []
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -11,7 +11,7 @@ from homeassistant.exceptions import HomeAssistantError
|
|||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant, assert_setup_component, \
|
from tests.common import get_test_home_assistant, assert_setup_component, \
|
||||||
fire_time_changed
|
fire_time_changed, mock_component
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -21,7 +21,7 @@ class TestAutomation(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('group')
|
mock_component(self.hass, 'group')
|
||||||
self.calls = []
|
self.calls = []
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -5,7 +5,8 @@ from homeassistant.core import callback
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
mock_mqtt_component, fire_mqtt_message, get_test_home_assistant)
|
mock_mqtt_component, fire_mqtt_message, get_test_home_assistant,
|
||||||
|
mock_component)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -15,7 +16,7 @@ class TestAutomationMQTT(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('group')
|
mock_component(self.hass, 'group')
|
||||||
mock_mqtt_component(self.hass)
|
mock_mqtt_component(self.hass)
|
||||||
self.calls = []
|
self.calls = []
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from homeassistant.core import callback
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -15,7 +15,7 @@ class TestAutomationNumericState(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('group')
|
mock_component(self.hass, 'group')
|
||||||
self.calls = []
|
self.calls = []
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -10,7 +10,8 @@ import homeassistant.util.dt as dt_util
|
|||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
fire_time_changed, get_test_home_assistant, assert_setup_component)
|
fire_time_changed, get_test_home_assistant, assert_setup_component,
|
||||||
|
mock_component)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -20,7 +21,7 @@ class TestAutomationState(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('group')
|
mock_component(self.hass, 'group')
|
||||||
self.hass.states.set('test.entity', 'hello')
|
self.hass.states.set('test.entity', 'hello')
|
||||||
self.calls = []
|
self.calls = []
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@ from homeassistant.components import sun
|
|||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from tests.common import fire_time_changed, get_test_home_assistant
|
from tests.common import (
|
||||||
|
fire_time_changed, get_test_home_assistant, mock_component)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -20,8 +21,8 @@ class TestAutomationSun(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('group')
|
mock_component(self.hass, 'group')
|
||||||
self.hass.config.components.add('sun')
|
mock_component(self.hass, 'sun')
|
||||||
|
|
||||||
self.calls = []
|
self.calls = []
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ from homeassistant.core import callback
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant, assert_setup_component
|
from tests.common import (
|
||||||
|
get_test_home_assistant, assert_setup_component, mock_component)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -15,7 +16,7 @@ class TestAutomationTemplate(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('group')
|
mock_component(self.hass, 'group')
|
||||||
self.hass.states.set('test.entity', 'hello')
|
self.hass.states.set('test.entity', 'hello')
|
||||||
self.calls = []
|
self.calls = []
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@ import homeassistant.util.dt as dt_util
|
|||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
fire_time_changed, get_test_home_assistant, assert_setup_component)
|
fire_time_changed, get_test_home_assistant, assert_setup_component,
|
||||||
|
mock_component)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -19,7 +20,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('group')
|
mock_component(self.hass, 'group')
|
||||||
self.calls = []
|
self.calls = []
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -5,7 +5,7 @@ from homeassistant.core import callback
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import automation, zone
|
from homeassistant.components import automation, zone
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
@ -15,7 +15,7 @@ class TestAutomationZone(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('group')
|
mock_component(self.hass, 'group')
|
||||||
assert setup_component(self.hass, zone.DOMAIN, {
|
assert setup_component(self.hass, zone.DOMAIN, {
|
||||||
'zone': {
|
'zone': {
|
||||||
'name': 'test',
|
'name': 'test',
|
||||||
|
@ -3,10 +3,10 @@ import unittest
|
|||||||
|
|
||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.binary_sensor as binary_sensor
|
import homeassistant.components.binary_sensor as binary_sensor
|
||||||
from tests.common import mock_mqtt_component, fire_mqtt_message
|
|
||||||
from homeassistant.const import (STATE_OFF, STATE_ON)
|
from homeassistant.const import (STATE_OFF, STATE_ON)
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import (
|
||||||
|
get_test_home_assistant, mock_mqtt_component, fire_mqtt_message)
|
||||||
|
|
||||||
|
|
||||||
class TestSensorMQTT(unittest.TestCase):
|
class TestSensorMQTT(unittest.TestCase):
|
||||||
@ -23,7 +23,6 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_setting_sensor_value_via_mqtt_message(self):
|
def test_setting_sensor_value_via_mqtt_message(self):
|
||||||
"""Test the setting of the value via MQTT."""
|
"""Test the setting of the value via MQTT."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, binary_sensor.DOMAIN, {
|
assert setup_component(self.hass, binary_sensor.DOMAIN, {
|
||||||
binary_sensor.DOMAIN: {
|
binary_sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -49,7 +48,6 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_valid_device_class(self):
|
def test_valid_device_class(self):
|
||||||
"""Test the setting of a valid sensor class."""
|
"""Test the setting of a valid sensor class."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, binary_sensor.DOMAIN, {
|
assert setup_component(self.hass, binary_sensor.DOMAIN, {
|
||||||
binary_sensor.DOMAIN: {
|
binary_sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -64,7 +62,6 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_device_class(self):
|
def test_invalid_device_class(self):
|
||||||
"""Test the setting of an invalid sensor class."""
|
"""Test the setting of an invalid sensor class."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, binary_sensor.DOMAIN, {
|
assert setup_component(self.hass, binary_sensor.DOMAIN, {
|
||||||
binary_sensor.DOMAIN: {
|
binary_sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
|
@ -9,7 +9,7 @@ from uvcclient import nvr
|
|||||||
|
|
||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components.camera import uvc
|
from homeassistant.components.camera import uvc
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_http_component
|
||||||
|
|
||||||
|
|
||||||
class TestUVCSetup(unittest.TestCase):
|
class TestUVCSetup(unittest.TestCase):
|
||||||
@ -18,8 +18,7 @@ class TestUVCSetup(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.http = mock.MagicMock()
|
mock_http_component(self.hass)
|
||||||
self.hass.config.components = set(['http'])
|
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
"""The tests for the generic_thermostat."""
|
"""The tests for the generic_thermostat."""
|
||||||
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
import unittest
|
import unittest
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component, async_setup_component
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_UNIT_OF_MEASUREMENT,
|
ATTR_UNIT_OF_MEASUREMENT,
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
@ -105,23 +106,6 @@ class TestClimateGenericThermostat(unittest.TestCase):
|
|||||||
self.assertEqual(35, state.attributes.get('max_temp'))
|
self.assertEqual(35, state.attributes.get('max_temp'))
|
||||||
self.assertEqual(None, state.attributes.get('temperature'))
|
self.assertEqual(None, state.attributes.get('temperature'))
|
||||||
|
|
||||||
def test_custom_setup_params(self):
|
|
||||||
"""Test the setup with custom parameters."""
|
|
||||||
self.hass.config.components.remove(climate.DOMAIN)
|
|
||||||
assert setup_component(self.hass, climate.DOMAIN, {'climate': {
|
|
||||||
'platform': 'generic_thermostat',
|
|
||||||
'name': 'test',
|
|
||||||
'heater': ENT_SWITCH,
|
|
||||||
'target_sensor': ENT_SENSOR,
|
|
||||||
'min_temp': MIN_TEMP,
|
|
||||||
'max_temp': MAX_TEMP,
|
|
||||||
'target_temp': TARGET_TEMP,
|
|
||||||
}})
|
|
||||||
state = self.hass.states.get(ENTITY)
|
|
||||||
self.assertEqual(MIN_TEMP, state.attributes.get('min_temp'))
|
|
||||||
self.assertEqual(MAX_TEMP, state.attributes.get('max_temp'))
|
|
||||||
self.assertEqual(TARGET_TEMP, state.attributes.get('temperature'))
|
|
||||||
|
|
||||||
def test_set_target_temp(self):
|
def test_set_target_temp(self):
|
||||||
"""Test the setting of the target temperature."""
|
"""Test the setting of the target temperature."""
|
||||||
climate.set_temperature(self.hass, 30)
|
climate.set_temperature(self.hass, 30)
|
||||||
@ -538,3 +522,23 @@ class TestClimateGenericThermostatMinCycle(unittest.TestCase):
|
|||||||
|
|
||||||
self.hass.services.register('switch', SERVICE_TURN_ON, log_call)
|
self.hass.services.register('switch', SERVICE_TURN_ON, log_call)
|
||||||
self.hass.services.register('switch', SERVICE_TURN_OFF, log_call)
|
self.hass.services.register('switch', SERVICE_TURN_OFF, log_call)
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_custom_setup_params(hass):
|
||||||
|
"""Test the setup with custom parameters."""
|
||||||
|
result = yield from async_setup_component(
|
||||||
|
hass, climate.DOMAIN, {'climate': {
|
||||||
|
'platform': 'generic_thermostat',
|
||||||
|
'name': 'test',
|
||||||
|
'heater': ENT_SWITCH,
|
||||||
|
'target_sensor': ENT_SENSOR,
|
||||||
|
'min_temp': MIN_TEMP,
|
||||||
|
'max_temp': MAX_TEMP,
|
||||||
|
'target_temp': TARGET_TEMP,
|
||||||
|
}})
|
||||||
|
assert result
|
||||||
|
state = hass.states.get(ENTITY)
|
||||||
|
assert state.attributes.get('min_temp') == MIN_TEMP
|
||||||
|
assert state.attributes.get('max_temp') == MAX_TEMP
|
||||||
|
assert state.attributes.get('temperature') == TARGET_TEMP
|
||||||
|
@ -15,6 +15,9 @@ def test_validate_config_ok(hass, test_client):
|
|||||||
with patch.object(config, 'SECTIONS', ['core']):
|
with patch.object(config, 'SECTIONS', ['core']):
|
||||||
yield from async_setup_component(hass, 'config', {})
|
yield from async_setup_component(hass, 'config', {})
|
||||||
|
|
||||||
|
# yield from hass.async_block_till_done()
|
||||||
|
yield from asyncio.sleep(0.1, loop=hass.loop)
|
||||||
|
|
||||||
hass.http.views[CheckConfigView.name].register(app.router)
|
hass.http.views[CheckConfigView.name].register(app.router)
|
||||||
client = yield from test_client(app)
|
client = yield from test_client(app)
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ from homeassistant.const import EVENT_COMPONENT_LOADED
|
|||||||
from homeassistant.bootstrap import async_setup_component, ATTR_COMPONENT
|
from homeassistant.bootstrap import async_setup_component, ATTR_COMPONENT
|
||||||
from homeassistant.components import config
|
from homeassistant.components import config
|
||||||
|
|
||||||
from tests.common import mock_http_component, mock_coro
|
from tests.common import mock_http_component, mock_coro, mock_component
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
@ -27,7 +27,7 @@ def test_config_setup(hass, loop):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_load_on_demand_already_loaded(hass, test_client):
|
def test_load_on_demand_already_loaded(hass, test_client):
|
||||||
"""Test getting suites."""
|
"""Test getting suites."""
|
||||||
hass.config.components.add('zwave')
|
mock_component(hass, 'zwave')
|
||||||
|
|
||||||
with patch.object(config, 'SECTIONS', []), \
|
with patch.object(config, 'SECTIONS', []), \
|
||||||
patch.object(config, 'ON_DEMAND', ['zwave']), \
|
patch.object(config, 'ON_DEMAND', ['zwave']), \
|
||||||
|
@ -4,9 +4,9 @@ import unittest
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.const import STATE_OPEN, STATE_CLOSED, STATE_UNKNOWN
|
from homeassistant.const import STATE_OPEN, STATE_CLOSED, STATE_UNKNOWN
|
||||||
import homeassistant.components.cover as cover
|
import homeassistant.components.cover as cover
|
||||||
from tests.common import mock_mqtt_component, fire_mqtt_message
|
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import (
|
||||||
|
get_test_home_assistant, mock_mqtt_component, fire_mqtt_message)
|
||||||
|
|
||||||
|
|
||||||
class TestCoverMQTT(unittest.TestCase):
|
class TestCoverMQTT(unittest.TestCase):
|
||||||
@ -23,7 +23,6 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_state_via_state_topic(self):
|
def test_state_via_state_topic(self):
|
||||||
"""Test the controlling state via topic."""
|
"""Test the controlling state via topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
cover.DOMAIN: {
|
cover.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -72,7 +71,6 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_state_via_template(self):
|
def test_state_via_template(self):
|
||||||
"""Test the controlling state via topic."""
|
"""Test the controlling state via topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
cover.DOMAIN: {
|
cover.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -101,7 +99,6 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_optimistic_state_change(self):
|
def test_optimistic_state_change(self):
|
||||||
"""Test changing state optimistically."""
|
"""Test changing state optimistically."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
cover.DOMAIN: {
|
cover.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -132,7 +129,6 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_send_open_cover_command(self):
|
def test_send_open_cover_command(self):
|
||||||
"""Test the sending of open_cover."""
|
"""Test the sending of open_cover."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
cover.DOMAIN: {
|
cover.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -156,7 +152,6 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_send_close_cover_command(self):
|
def test_send_close_cover_command(self):
|
||||||
"""Test the sending of close_cover."""
|
"""Test the sending of close_cover."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
cover.DOMAIN: {
|
cover.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -180,7 +175,6 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_send_stop__cover_command(self):
|
def test_send_stop__cover_command(self):
|
||||||
"""Test the sending of stop_cover."""
|
"""Test the sending of stop_cover."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
cover.DOMAIN: {
|
cover.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -204,7 +198,6 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_current_cover_position(self):
|
def test_current_cover_position(self):
|
||||||
"""Test the current cover position."""
|
"""Test the current cover position."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
cover.DOMAIN: {
|
cover.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
|
@ -6,7 +6,7 @@ import pytest
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import rfxtrx as rfxtrx_core
|
from homeassistant.components import rfxtrx as rfxtrx_core
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
|
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
|
||||||
@ -16,7 +16,7 @@ class TestCoverRfxtrx(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components = set(['rfxtrx'])
|
mock_component('rfxtrx')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
|
@ -17,7 +17,8 @@ from homeassistant.const import (CONF_PLATFORM, CONF_PASSWORD, CONF_USERNAME,
|
|||||||
CONF_HOST)
|
CONF_HOST)
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
get_test_home_assistant, get_test_config_dir, assert_setup_component)
|
get_test_home_assistant, get_test_config_dir, assert_setup_component,
|
||||||
|
mock_component)
|
||||||
|
|
||||||
FAKEFILE = None
|
FAKEFILE = None
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ class TestComponentsDeviceTrackerASUSWRT(unittest.TestCase):
|
|||||||
def setup_method(self, _):
|
def setup_method(self, _):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components = set(['zone'])
|
mock_component(self.hass, 'zone')
|
||||||
|
|
||||||
def teardown_method(self, _):
|
def teardown_method(self, _):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
|
@ -16,7 +16,8 @@ from homeassistant.components.device_tracker import DOMAIN
|
|||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
get_test_home_assistant, assert_setup_component, load_fixture)
|
get_test_home_assistant, assert_setup_component, load_fixture,
|
||||||
|
mock_component)
|
||||||
|
|
||||||
from ...test_util.aiohttp import mock_aiohttp_client
|
from ...test_util.aiohttp import mock_aiohttp_client
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ class TestDdwrt(unittest.TestCase):
|
|||||||
def setup_method(self, _):
|
def setup_method(self, _):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components = set(['zone'])
|
mock_component(self.hass, 'zone')
|
||||||
|
|
||||||
def teardown_method(self, _):
|
def teardown_method(self, _):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
|
@ -43,7 +43,6 @@ class TestComponentsDeviceTrackerMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
dev_id = 'paulus'
|
dev_id = 'paulus'
|
||||||
topic = '/location/paulus'
|
topic = '/location/paulus'
|
||||||
self.hass.config.components = set(['mqtt', 'zone'])
|
|
||||||
assert setup_component(self.hass, device_tracker.DOMAIN, {
|
assert setup_component(self.hass, device_tracker.DOMAIN, {
|
||||||
device_tracker.DOMAIN: {
|
device_tracker.DOMAIN: {
|
||||||
CONF_PLATFORM: 'mqtt',
|
CONF_PLATFORM: 'mqtt',
|
||||||
|
@ -13,7 +13,8 @@ import homeassistant.components.device_tracker.upc_connect as platform
|
|||||||
from homeassistant.util.async import run_coroutine_threadsafe
|
from homeassistant.util.async import run_coroutine_threadsafe
|
||||||
|
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
get_test_home_assistant, assert_setup_component, load_fixture)
|
get_test_home_assistant, assert_setup_component, load_fixture,
|
||||||
|
mock_component)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ class TestUPCConnect(object):
|
|||||||
def setup_method(self):
|
def setup_method(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components = set(['zone'])
|
mock_component(self.hass, 'zone')
|
||||||
|
|
||||||
self.host = "127.0.0.1"
|
self.host = "127.0.0.1"
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""The tests for the Home Assistant HTTP component."""
|
"""The tests for the Home Assistant HTTP component."""
|
||||||
import asyncio
|
import asyncio
|
||||||
import requests
|
import requests
|
||||||
from unittest.mock import MagicMock
|
|
||||||
|
|
||||||
from homeassistant import bootstrap, const
|
from homeassistant import bootstrap, const
|
||||||
import homeassistant.components.http as http
|
import homeassistant.components.http as http
|
||||||
@ -157,46 +156,48 @@ def test_registering_view_while_running(hass, test_client):
|
|||||||
assert text == 'hello'
|
assert text == 'hello'
|
||||||
|
|
||||||
|
|
||||||
def test_api_base_url(loop):
|
@asyncio.coroutine
|
||||||
|
def test_api_base_url_with_domain(hass):
|
||||||
"""Test setting api url."""
|
"""Test setting api url."""
|
||||||
hass = MagicMock()
|
result = yield from bootstrap.async_setup_component(hass, 'http', {
|
||||||
hass.loop = loop
|
|
||||||
|
|
||||||
assert loop.run_until_complete(
|
|
||||||
bootstrap.async_setup_component(hass, 'http', {
|
|
||||||
'http': {
|
'http': {
|
||||||
'base_url': 'example.com'
|
'base_url': 'example.com'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
assert result
|
||||||
|
|
||||||
assert hass.config.api.base_url == 'http://example.com'
|
assert hass.config.api.base_url == 'http://example.com'
|
||||||
|
|
||||||
assert loop.run_until_complete(
|
|
||||||
bootstrap.async_setup_component(hass, 'http', {
|
@asyncio.coroutine
|
||||||
|
def test_api_base_url_with_ip(hass):
|
||||||
|
"""Test setting api url."""
|
||||||
|
result = yield from bootstrap.async_setup_component(hass, 'http', {
|
||||||
'http': {
|
'http': {
|
||||||
'server_host': '1.1.1.1'
|
'server_host': '1.1.1.1'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
assert result
|
||||||
|
|
||||||
assert hass.config.api.base_url == 'http://1.1.1.1:8123'
|
assert hass.config.api.base_url == 'http://1.1.1.1:8123'
|
||||||
|
|
||||||
assert loop.run_until_complete(
|
|
||||||
bootstrap.async_setup_component(hass, 'http', {
|
@asyncio.coroutine
|
||||||
|
def test_api_base_url_with_ip_port(hass):
|
||||||
|
"""Test setting api url."""
|
||||||
|
result = yield from bootstrap.async_setup_component(hass, 'http', {
|
||||||
'http': {
|
'http': {
|
||||||
'server_host': '1.1.1.1'
|
'base_url': '1.1.1.1:8124'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
assert result
|
||||||
|
assert hass.config.api.base_url == 'http://1.1.1.1:8124'
|
||||||
|
|
||||||
assert hass.config.api.base_url == 'http://1.1.1.1:8123'
|
|
||||||
|
|
||||||
assert loop.run_until_complete(
|
@asyncio.coroutine
|
||||||
bootstrap.async_setup_component(hass, 'http', {
|
def test_api_no_base_url(hass):
|
||||||
|
"""Test setting api url."""
|
||||||
|
result = yield from bootstrap.async_setup_component(hass, 'http', {
|
||||||
'http': {
|
'http': {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
assert result
|
||||||
|
|
||||||
assert hass.config.api.base_url == 'http://127.0.0.1:8123'
|
assert hass.config.api.base_url == 'http://127.0.0.1:8123'
|
||||||
|
@ -8,7 +8,7 @@ from homeassistant.bootstrap import setup_component, async_setup_component
|
|||||||
import homeassistant.components.light as light
|
import homeassistant.components.light as light
|
||||||
from homeassistant.helpers.restore_state import DATA_RESTORE_CACHE
|
from homeassistant.helpers.restore_state import DATA_RESTORE_CACHE
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
ENTITY_LIGHT = 'light.bed_light'
|
ENTITY_LIGHT = 'light.bed_light'
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ class TestDemoLight(unittest.TestCase):
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def test_restore_state(hass):
|
def test_restore_state(hass):
|
||||||
"""Test state gets restored."""
|
"""Test state gets restored."""
|
||||||
hass.config.components.add('recorder')
|
mock_component(hass, 'recorder')
|
||||||
hass.state = CoreState.starting
|
hass.state = CoreState.starting
|
||||||
hass.data[DATA_RESTORE_CACHE] = {
|
hass.data[DATA_RESTORE_CACHE] = {
|
||||||
'light.bed_light': State('light.bed_light', 'on', {
|
'light.bed_light': State('light.bed_light', 'on', {
|
||||||
|
@ -100,7 +100,6 @@ class TestLightMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_fail_setup_if_no_command_topic(self):
|
def test_fail_setup_if_no_command_topic(self):
|
||||||
"""Test if command fails with command topic."""
|
"""Test if command fails with command topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(0):
|
with assert_setup_component(0):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -113,7 +112,6 @@ class TestLightMQTT(unittest.TestCase):
|
|||||||
def test_no_color_or_brightness_or_color_temp_if_no_topics(self): \
|
def test_no_color_or_brightness_or_color_temp_if_no_topics(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test if there is no color and brightness if no topic."""
|
"""Test if there is no color and brightness if no topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -158,7 +156,6 @@ class TestLightMQTT(unittest.TestCase):
|
|||||||
'payload_off': 0
|
'payload_off': 0
|
||||||
}}
|
}}
|
||||||
|
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, config)
|
assert setup_component(self.hass, light.DOMAIN, config)
|
||||||
|
|
||||||
@ -214,7 +211,6 @@ class TestLightMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_controlling_scale(self):
|
def test_controlling_scale(self):
|
||||||
"""Test the controlling scale."""
|
"""Test the controlling scale."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -277,7 +273,6 @@ class TestLightMQTT(unittest.TestCase):
|
|||||||
'rgb_value_template': '{{ value_json.hello | join(",") }}',
|
'rgb_value_template': '{{ value_json.hello | join(",") }}',
|
||||||
}}
|
}}
|
||||||
|
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, config)
|
assert setup_component(self.hass, light.DOMAIN, config)
|
||||||
|
|
||||||
@ -317,7 +312,6 @@ class TestLightMQTT(unittest.TestCase):
|
|||||||
'payload_off': 'off'
|
'payload_off': 'off'
|
||||||
}}
|
}}
|
||||||
|
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, config)
|
assert setup_component(self.hass, light.DOMAIN, config)
|
||||||
|
|
||||||
@ -367,7 +361,6 @@ class TestLightMQTT(unittest.TestCase):
|
|||||||
'state_topic': 'test_light_rgb/status',
|
'state_topic': 'test_light_rgb/status',
|
||||||
}}
|
}}
|
||||||
|
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, config)
|
assert setup_component(self.hass, light.DOMAIN, config)
|
||||||
|
|
||||||
@ -392,7 +385,6 @@ class TestLightMQTT(unittest.TestCase):
|
|||||||
'state_topic': 'test_light_rgb/status'
|
'state_topic': 'test_light_rgb/status'
|
||||||
}}
|
}}
|
||||||
|
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, config)
|
assert setup_component(self.hass, light.DOMAIN, config)
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
def test_fail_setup_if_no_command_topic(self): \
|
def test_fail_setup_if_no_command_topic(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test if setup fails with no command topic."""
|
"""Test if setup fails with no command topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(0):
|
with assert_setup_component(0):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -66,7 +65,6 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
def test_no_color_or_brightness_if_no_config(self): \
|
def test_no_color_or_brightness_if_no_config(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test if there is no color and brightness if they aren't defined."""
|
"""Test if there is no color and brightness if they aren't defined."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
@ -92,7 +90,6 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
def test_controlling_state_via_topic(self): \
|
def test_controlling_state_via_topic(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test the controlling of the state via topic."""
|
"""Test the controlling of the state via topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
@ -152,7 +149,6 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
def test_sending_mqtt_commands_and_optimistic(self): \
|
def test_sending_mqtt_commands_and_optimistic(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test the sending of command in optimistic mode."""
|
"""Test the sending of command in optimistic mode."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
@ -208,7 +204,6 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
def test_flash_short_and_long(self): \
|
def test_flash_short_and_long(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test for flash length being sent when included."""
|
"""Test for flash length being sent when included."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
@ -250,7 +245,6 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
|
|
||||||
def test_transition(self):
|
def test_transition(self):
|
||||||
"""Test for transition time being sent when included."""
|
"""Test for transition time being sent when included."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
@ -292,7 +286,6 @@ class TestLightMQTTJSON(unittest.TestCase):
|
|||||||
def test_invalid_color_and_brightness_values(self): \
|
def test_invalid_color_and_brightness_values(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test that invalid color/brightness values are ignored."""
|
"""Test that invalid color/brightness values are ignored."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
'platform': 'mqtt_json',
|
'platform': 'mqtt_json',
|
||||||
|
@ -45,7 +45,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
def test_setup_fails(self): \
|
def test_setup_fails(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test that setup fails with missing required configuration items."""
|
"""Test that setup fails with missing required configuration items."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(0):
|
with assert_setup_component(0):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -58,7 +57,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
def test_state_change_via_topic(self): \
|
def test_state_change_via_topic(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test state change via topic."""
|
"""Test state change via topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -93,7 +91,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
def test_state_brightness_color_effect_change_via_topic(self): \
|
def test_state_brightness_color_effect_change_via_topic(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test state, brightness, color and effect change via topic."""
|
"""Test state, brightness, color and effect change via topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -170,7 +167,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
def test_optimistic(self): \
|
def test_optimistic(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test optimistic mode."""
|
"""Test optimistic mode."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -232,7 +228,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
def test_flash(self): \
|
def test_flash(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test flash."""
|
"""Test flash."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -276,7 +271,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
|
|
||||||
def test_transition(self):
|
def test_transition(self):
|
||||||
"""Test for transition time being sent when included."""
|
"""Test for transition time being sent when included."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
@ -320,7 +314,6 @@ class TestLightMQTTTemplate(unittest.TestCase):
|
|||||||
def test_invalid_values(self): \
|
def test_invalid_values(self): \
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
"""Test that invalid values are ignored."""
|
"""Test that invalid values are ignored."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
with assert_setup_component(1):
|
with assert_setup_component(1):
|
||||||
assert setup_component(self.hass, light.DOMAIN, {
|
assert setup_component(self.hass, light.DOMAIN, {
|
||||||
light.DOMAIN: {
|
light.DOMAIN: {
|
||||||
|
@ -6,7 +6,7 @@ import pytest
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import rfxtrx as rfxtrx_core
|
from homeassistant.components import rfxtrx as rfxtrx_core
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
|
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
|
||||||
@ -16,7 +16,7 @@ class TestLightRfxtrx(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components = set(['rfxtrx'])
|
mock_component(self.hass, 'rfxtrx')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
|
@ -23,7 +23,6 @@ class TestLockMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_controlling_state_via_topic(self):
|
def test_controlling_state_via_topic(self):
|
||||||
"""Test the controlling state via topic."""
|
"""Test the controlling state via topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, lock.DOMAIN, {
|
assert setup_component(self.hass, lock.DOMAIN, {
|
||||||
lock.DOMAIN: {
|
lock.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -53,7 +52,6 @@ class TestLockMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_sending_mqtt_commands_and_optimistic(self):
|
def test_sending_mqtt_commands_and_optimistic(self):
|
||||||
"""Test the sending MQTT commands in optimistic mode."""
|
"""Test the sending MQTT commands in optimistic mode."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, lock.DOMAIN, {
|
assert setup_component(self.hass, lock.DOMAIN, {
|
||||||
lock.DOMAIN: {
|
lock.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -87,7 +85,6 @@ class TestLockMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_controlling_state_via_topic_and_json_message(self):
|
def test_controlling_state_via_topic_and_json_message(self):
|
||||||
"""Test the controlling state via topic and JSON message."""
|
"""Test the controlling state via topic and JSON message."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, lock.DOMAIN, {
|
assert setup_component(self.hass, lock.DOMAIN, {
|
||||||
lock.DOMAIN: {
|
lock.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
"""The tests for the Universal Media player platform."""
|
"""The tests for the Universal Media player platform."""
|
||||||
import asyncio
|
|
||||||
from copy import copy
|
from copy import copy
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
@ -258,7 +257,6 @@ class TestMediaPlayer(unittest.TestCase):
|
|||||||
bad_config = {'platform': 'universal'}
|
bad_config = {'platform': 'universal'}
|
||||||
entities = []
|
entities = []
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def add_devices(new_entities):
|
def add_devices(new_entities):
|
||||||
"""Add devices to list."""
|
"""Add devices to list."""
|
||||||
for dev in new_entities:
|
for dev in new_entities:
|
||||||
|
@ -4,7 +4,8 @@ from unittest.mock import Mock, MagicMock, patch
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
import homeassistant.components.mqtt as mqtt
|
import homeassistant.components.mqtt as mqtt
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant, mock_coro
|
from tests.common import (
|
||||||
|
get_test_home_assistant, mock_coro, mock_http_component)
|
||||||
|
|
||||||
|
|
||||||
class TestMQTT:
|
class TestMQTT:
|
||||||
@ -13,7 +14,7 @@ class TestMQTT:
|
|||||||
def setup_method(self, method):
|
def setup_method(self, method):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components.add('http')
|
mock_http_component(self.hass, 'super_secret')
|
||||||
|
|
||||||
def teardown_method(self, method):
|
def teardown_method(self, method):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
@ -33,13 +34,21 @@ class TestMQTT:
|
|||||||
self.hass.config.api = MagicMock(api_password=password)
|
self.hass.config.api = MagicMock(api_password=password)
|
||||||
assert setup_component(self.hass, mqtt.DOMAIN, {})
|
assert setup_component(self.hass, mqtt.DOMAIN, {})
|
||||||
assert mock_mqtt.called
|
assert mock_mqtt.called
|
||||||
|
from pprint import pprint
|
||||||
|
pprint(mock_mqtt.mock_calls)
|
||||||
assert mock_mqtt.mock_calls[1][1][5] == 'homeassistant'
|
assert mock_mqtt.mock_calls[1][1][5] == 'homeassistant'
|
||||||
assert mock_mqtt.mock_calls[1][1][6] == password
|
assert mock_mqtt.mock_calls[1][1][6] == password
|
||||||
|
|
||||||
mock_mqtt.reset_mock()
|
@patch('passlib.apps.custom_app_context', Mock(return_value=''))
|
||||||
|
@patch('tempfile.NamedTemporaryFile', Mock(return_value=MagicMock()))
|
||||||
|
@patch('hbmqtt.broker.Broker', Mock(return_value=MagicMock()))
|
||||||
|
@patch('hbmqtt.broker.Broker.start', Mock(return_value=mock_coro()))
|
||||||
|
@patch('homeassistant.components.mqtt.MQTT')
|
||||||
|
def test_creating_config_with_http_no_pass(self, mock_mqtt):
|
||||||
|
"""Test if the MQTT server gets started and subscribe/publish msg."""
|
||||||
mock_mqtt().async_connect.return_value = mock_coro(True)
|
mock_mqtt().async_connect.return_value = mock_coro(True)
|
||||||
|
self.hass.bus.listen_once = MagicMock()
|
||||||
|
|
||||||
self.hass.config.components = set(['http'])
|
|
||||||
self.hass.config.api = MagicMock(api_password=None)
|
self.hass.config.api = MagicMock(api_password=None)
|
||||||
assert setup_component(self.hass, mqtt.DOMAIN, {})
|
assert setup_component(self.hass, mqtt.DOMAIN, {})
|
||||||
assert mock_mqtt.called
|
assert mock_mqtt.called
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
"""The tests for the notify demo platform."""
|
"""The tests for the notify demo platform."""
|
||||||
import asyncio
|
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
@ -17,12 +16,6 @@ CONFIG = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def mock_setup_platform():
|
|
||||||
"""Mock prepare_setup_platform."""
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class TestNotifyDemo(unittest.TestCase):
|
class TestNotifyDemo(unittest.TestCase):
|
||||||
"""Test the demo notify."""
|
"""Test the demo notify."""
|
||||||
|
|
||||||
@ -52,15 +45,6 @@ class TestNotifyDemo(unittest.TestCase):
|
|||||||
"""Test setup."""
|
"""Test setup."""
|
||||||
self._setup_notify()
|
self._setup_notify()
|
||||||
|
|
||||||
@patch('homeassistant.bootstrap.async_prepare_setup_platform',
|
|
||||||
return_value=mock_setup_platform())
|
|
||||||
def test_no_prepare_setup_platform(self, mock_prep_setup_platform):
|
|
||||||
"""Test missing notify platform."""
|
|
||||||
with assert_setup_component(0):
|
|
||||||
setup_component(self.hass, notify.DOMAIN, CONFIG)
|
|
||||||
|
|
||||||
assert mock_prep_setup_platform.called
|
|
||||||
|
|
||||||
@patch('homeassistant.components.notify.demo.get_service', autospec=True)
|
@patch('homeassistant.components.notify.demo.get_service', autospec=True)
|
||||||
def test_no_notify_service(self, mock_demo_get_service):
|
def test_no_notify_service(self, mock_demo_get_service):
|
||||||
"""Test missing platform notify service instance."""
|
"""Test missing platform notify service instance."""
|
||||||
|
@ -5,7 +5,7 @@ from homeassistant.bootstrap import setup_component
|
|||||||
import homeassistant.components.sensor as sensor
|
import homeassistant.components.sensor as sensor
|
||||||
from tests.common import mock_mqtt_component, fire_mqtt_message
|
from tests.common import mock_mqtt_component, fire_mqtt_message
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
|
|
||||||
class TestSensorMQTT(unittest.TestCase):
|
class TestSensorMQTT(unittest.TestCase):
|
||||||
@ -22,7 +22,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_setting_sensor_value_via_mqtt_message(self):
|
def test_setting_sensor_value_via_mqtt_message(self):
|
||||||
"""Test the setting of the value via MQTT."""
|
"""Test the setting of the value via MQTT."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
mock_component(self.hass, 'mqtt')
|
||||||
assert setup_component(self.hass, sensor.DOMAIN, {
|
assert setup_component(self.hass, sensor.DOMAIN, {
|
||||||
sensor.DOMAIN: {
|
sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -42,7 +42,7 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_setting_sensor_value_via_mqtt_json_message(self):
|
def test_setting_sensor_value_via_mqtt_json_message(self):
|
||||||
"""Test the setting of the value via MQTT with JSON playload."""
|
"""Test the setting of the value via MQTT with JSON playload."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
mock_component(self.hass, 'mqtt')
|
||||||
assert setup_component(self.hass, sensor.DOMAIN, {
|
assert setup_component(self.hass, sensor.DOMAIN, {
|
||||||
sensor.DOMAIN: {
|
sensor.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
|
@ -5,7 +5,8 @@ from homeassistant.bootstrap import setup_component
|
|||||||
import homeassistant.components.sensor as sensor
|
import homeassistant.components.sensor as sensor
|
||||||
from homeassistant.components import pilight
|
from homeassistant.components import pilight
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant, assert_setup_component
|
from tests.common import (
|
||||||
|
get_test_home_assistant, assert_setup_component, mock_component)
|
||||||
|
|
||||||
HASS = None
|
HASS = None
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ def setup_function():
|
|||||||
global HASS
|
global HASS
|
||||||
|
|
||||||
HASS = get_test_home_assistant()
|
HASS = get_test_home_assistant()
|
||||||
HASS.config.components = set(['pilight'])
|
mock_component(HASS, 'pilight')
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
|
@ -7,7 +7,7 @@ from homeassistant.bootstrap import setup_component
|
|||||||
from homeassistant.components import rfxtrx as rfxtrx_core
|
from homeassistant.components import rfxtrx as rfxtrx_core
|
||||||
from homeassistant.const import TEMP_CELSIUS
|
from homeassistant.const import TEMP_CELSIUS
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
|
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
|
||||||
@ -17,7 +17,7 @@ class TestSensorRfxtrx(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components = set(['rfxtrx'])
|
mock_component(self.hass, 'rfxtrx')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
|
@ -22,7 +22,6 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_controlling_state_via_topic(self):
|
def test_controlling_state_via_topic(self):
|
||||||
"""Test the controlling state via topic."""
|
"""Test the controlling state via topic."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, switch.DOMAIN, {
|
assert setup_component(self.hass, switch.DOMAIN, {
|
||||||
switch.DOMAIN: {
|
switch.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -52,7 +51,6 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_sending_mqtt_commands_and_optimistic(self):
|
def test_sending_mqtt_commands_and_optimistic(self):
|
||||||
"""Test the sending MQTT commands in optimistic mode."""
|
"""Test the sending MQTT commands in optimistic mode."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, switch.DOMAIN, {
|
assert setup_component(self.hass, switch.DOMAIN, {
|
||||||
switch.DOMAIN: {
|
switch.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
@ -86,7 +84,6 @@ class TestSensorMQTT(unittest.TestCase):
|
|||||||
|
|
||||||
def test_controlling_state_via_topic_and_json_message(self):
|
def test_controlling_state_via_topic_and_json_message(self):
|
||||||
"""Test the controlling state via topic and JSON message."""
|
"""Test the controlling state via topic and JSON message."""
|
||||||
self.hass.config.components = set(['mqtt'])
|
|
||||||
assert setup_component(self.hass, switch.DOMAIN, {
|
assert setup_component(self.hass, switch.DOMAIN, {
|
||||||
switch.DOMAIN: {
|
switch.DOMAIN: {
|
||||||
'platform': 'mqtt',
|
'platform': 'mqtt',
|
||||||
|
@ -6,7 +6,7 @@ import pytest
|
|||||||
from homeassistant.bootstrap import setup_component
|
from homeassistant.bootstrap import setup_component
|
||||||
from homeassistant.components import rfxtrx as rfxtrx_core
|
from homeassistant.components import rfxtrx as rfxtrx_core
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
|
@pytest.mark.skipif("os.environ.get('RFXTRX') != 'RUN'")
|
||||||
@ -16,7 +16,7 @@ class TestSwitchRfxtrx(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Setup things to be run when tests are started."""
|
"""Setup things to be run when tests are started."""
|
||||||
self.hass = get_test_home_assistant()
|
self.hass = get_test_home_assistant()
|
||||||
self.hass.config.components = set(['rfxtrx'])
|
mock_component(self.hass, 'rfxtrx')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Stop everything that was started."""
|
"""Stop everything that was started."""
|
||||||
|
@ -4,7 +4,7 @@ import asyncio
|
|||||||
import unittest
|
import unittest
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant, mock_component
|
||||||
|
|
||||||
from homeassistant.core import CoreState, State
|
from homeassistant.core import CoreState, State
|
||||||
from homeassistant.bootstrap import setup_component, async_setup_component
|
from homeassistant.bootstrap import setup_component, async_setup_component
|
||||||
@ -118,7 +118,7 @@ def test_restore_state(hass):
|
|||||||
}
|
}
|
||||||
|
|
||||||
hass.state = CoreState.starting
|
hass.state = CoreState.starting
|
||||||
hass.config.components.add('recorder')
|
mock_component(hass, 'recorder')
|
||||||
|
|
||||||
yield from async_setup_component(hass, DOMAIN, {
|
yield from async_setup_component(hass, DOMAIN, {
|
||||||
DOMAIN: {
|
DOMAIN: {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user