2015-01-16 07:32:27 +00:00
|
|
|
"""
|
2016-03-07 19:20:07 +00:00
|
|
|
Allow to setup simple automation rules via the config file.
|
2015-11-09 12:12:18 +00:00
|
|
|
|
|
|
|
For more details about this component, please refer to the documentation at
|
|
|
|
https://home-assistant.io/components/automation/
|
2015-01-16 07:32:27 +00:00
|
|
|
"""
|
2016-10-01 08:22:13 +00:00
|
|
|
import asyncio
|
2016-08-26 06:25:57 +00:00
|
|
|
from functools import partial
|
2015-01-16 07:32:27 +00:00
|
|
|
import logging
|
2016-09-04 15:15:52 +00:00
|
|
|
import os
|
2015-01-16 07:32:27 +00:00
|
|
|
|
2016-04-04 19:18:58 +00:00
|
|
|
import voluptuous as vol
|
|
|
|
|
2016-10-16 16:35:46 +00:00
|
|
|
from homeassistant.core import callback
|
2016-09-07 13:59:16 +00:00
|
|
|
from homeassistant.bootstrap import prepare_setup_platform
|
2016-09-04 15:15:52 +00:00
|
|
|
from homeassistant import config as conf_util
|
2016-08-26 06:25:57 +00:00
|
|
|
from homeassistant.const import (
|
|
|
|
ATTR_ENTITY_ID, CONF_PLATFORM, STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF,
|
|
|
|
SERVICE_TOGGLE)
|
2015-09-14 07:02:33 +00:00
|
|
|
from homeassistant.components import logbook
|
2016-04-28 10:03:57 +00:00
|
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
|
|
from homeassistant.helpers import extract_domain_configs, script, condition
|
2016-08-26 06:25:57 +00:00
|
|
|
from homeassistant.helpers.entity import ToggleEntity
|
|
|
|
from homeassistant.helpers.entity_component import EntityComponent
|
2016-04-04 19:18:58 +00:00
|
|
|
from homeassistant.loader import get_platform
|
2016-08-26 06:25:57 +00:00
|
|
|
from homeassistant.util.dt import utcnow
|
2016-04-04 19:18:58 +00:00
|
|
|
import homeassistant.helpers.config_validation as cv
|
2016-10-01 08:22:13 +00:00
|
|
|
from homeassistant.util.async import run_coroutine_threadsafe
|
2015-01-16 07:32:27 +00:00
|
|
|
|
2015-09-15 15:56:06 +00:00
|
|
|
DOMAIN = 'automation'
|
2016-08-26 06:25:57 +00:00
|
|
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
2015-01-16 07:32:27 +00:00
|
|
|
|
2015-09-15 15:56:06 +00:00
|
|
|
DEPENDENCIES = ['group']
|
2015-01-16 07:32:27 +00:00
|
|
|
|
2016-10-05 04:20:48 +00:00
|
|
|
GROUP_NAME_ALL_AUTOMATIONS = 'all automations'
|
|
|
|
|
2015-09-15 15:56:06 +00:00
|
|
|
CONF_ALIAS = 'alias'
|
2016-09-20 06:39:07 +00:00
|
|
|
CONF_HIDE_ENTITY = 'hide_entity'
|
2015-09-15 05:05:40 +00:00
|
|
|
|
2015-09-15 15:56:06 +00:00
|
|
|
CONF_CONDITION = 'condition'
|
2015-09-15 05:05:40 +00:00
|
|
|
CONF_ACTION = 'action'
|
2015-09-15 15:56:06 +00:00
|
|
|
CONF_TRIGGER = 'trigger'
|
|
|
|
CONF_CONDITION_TYPE = 'condition_type'
|
2016-10-04 06:41:08 +00:00
|
|
|
CONF_INITIAL_STATE = 'initial_state'
|
2015-09-15 15:56:06 +00:00
|
|
|
|
|
|
|
CONDITION_USE_TRIGGER_VALUES = 'use_trigger_values'
|
|
|
|
CONDITION_TYPE_AND = 'and'
|
|
|
|
CONDITION_TYPE_OR = 'or'
|
2015-09-15 05:51:28 +00:00
|
|
|
|
|
|
|
DEFAULT_CONDITION_TYPE = CONDITION_TYPE_AND
|
2016-09-20 06:39:07 +00:00
|
|
|
DEFAULT_HIDE_ENTITY = False
|
2016-10-04 06:41:08 +00:00
|
|
|
DEFAULT_INITIAL_STATE = True
|
2015-01-16 07:32:27 +00:00
|
|
|
|
2016-08-26 06:25:57 +00:00
|
|
|
ATTR_LAST_TRIGGERED = 'last_triggered'
|
|
|
|
ATTR_VARIABLES = 'variables'
|
|
|
|
SERVICE_TRIGGER = 'trigger'
|
2016-09-04 15:15:52 +00:00
|
|
|
SERVICE_RELOAD = 'reload'
|
2016-08-26 06:25:57 +00:00
|
|
|
|
2015-01-16 07:32:27 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
def _platform_validator(config):
|
|
|
|
"""Validate it is a valid platform."""
|
|
|
|
platform = get_platform(DOMAIN, config[CONF_PLATFORM])
|
2016-04-04 19:18:58 +00:00
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
if not hasattr(platform, 'TRIGGER_SCHEMA'):
|
|
|
|
return config
|
2016-04-04 19:18:58 +00:00
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
return getattr(platform, 'TRIGGER_SCHEMA')(config)
|
2016-04-04 19:18:58 +00:00
|
|
|
|
|
|
|
_TRIGGER_SCHEMA = vol.All(
|
|
|
|
cv.ensure_list,
|
|
|
|
[
|
|
|
|
vol.All(
|
|
|
|
vol.Schema({
|
|
|
|
vol.Required(CONF_PLATFORM): cv.platform_validator(DOMAIN)
|
|
|
|
}, extra=vol.ALLOW_EXTRA),
|
2016-10-01 08:22:13 +00:00
|
|
|
_platform_validator
|
2016-04-04 19:18:58 +00:00
|
|
|
),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
_CONDITION_SCHEMA = vol.All(cv.ensure_list, [cv.CONDITION_SCHEMA])
|
2016-04-04 19:18:58 +00:00
|
|
|
|
|
|
|
PLATFORM_SCHEMA = vol.Schema({
|
|
|
|
CONF_ALIAS: cv.string,
|
2016-10-04 06:41:08 +00:00
|
|
|
vol.Optional(CONF_INITIAL_STATE,
|
|
|
|
default=DEFAULT_INITIAL_STATE): cv.boolean,
|
2016-09-20 06:39:07 +00:00
|
|
|
vol.Optional(CONF_HIDE_ENTITY, default=DEFAULT_HIDE_ENTITY): cv.boolean,
|
2016-04-04 19:18:58 +00:00
|
|
|
vol.Required(CONF_TRIGGER): _TRIGGER_SCHEMA,
|
2016-08-26 06:25:57 +00:00
|
|
|
vol.Optional(CONF_CONDITION): _CONDITION_SCHEMA,
|
2016-04-22 02:36:14 +00:00
|
|
|
vol.Required(CONF_ACTION): cv.SCRIPT_SCHEMA,
|
2016-04-04 19:18:58 +00:00
|
|
|
})
|
|
|
|
|
2016-08-26 06:25:57 +00:00
|
|
|
SERVICE_SCHEMA = vol.Schema({
|
|
|
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
|
|
|
})
|
|
|
|
|
|
|
|
TRIGGER_SERVICE_SCHEMA = vol.Schema({
|
|
|
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
|
|
|
vol.Optional(ATTR_VARIABLES, default={}): dict,
|
|
|
|
})
|
|
|
|
|
2016-09-04 15:15:52 +00:00
|
|
|
RELOAD_SERVICE_SCHEMA = vol.Schema({})
|
|
|
|
|
2016-08-26 06:25:57 +00:00
|
|
|
|
|
|
|
def is_on(hass, entity_id=None):
|
|
|
|
"""
|
|
|
|
Return true if specified automation entity_id is on.
|
|
|
|
|
|
|
|
Check all automation if no entity_id specified.
|
|
|
|
"""
|
|
|
|
entity_ids = [entity_id] if entity_id else hass.states.entity_ids(DOMAIN)
|
|
|
|
return any(hass.states.is_state(entity_id, STATE_ON)
|
|
|
|
for entity_id in entity_ids)
|
|
|
|
|
|
|
|
|
|
|
|
def turn_on(hass, entity_id=None):
|
|
|
|
"""Turn on specified automation or all."""
|
|
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
|
|
hass.services.call(DOMAIN, SERVICE_TURN_ON, data)
|
|
|
|
|
|
|
|
|
|
|
|
def turn_off(hass, entity_id=None):
|
|
|
|
"""Turn off specified automation or all."""
|
|
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
|
|
hass.services.call(DOMAIN, SERVICE_TURN_OFF, data)
|
|
|
|
|
|
|
|
|
|
|
|
def toggle(hass, entity_id=None):
|
|
|
|
"""Toggle specified automation or all."""
|
|
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
|
|
hass.services.call(DOMAIN, SERVICE_TOGGLE, data)
|
|
|
|
|
|
|
|
|
|
|
|
def trigger(hass, entity_id=None):
|
|
|
|
"""Trigger specified automation or all."""
|
|
|
|
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
|
|
|
hass.services.call(DOMAIN, SERVICE_TRIGGER, data)
|
|
|
|
|
2016-04-04 19:18:58 +00:00
|
|
|
|
2016-09-04 15:15:52 +00:00
|
|
|
def reload(hass):
|
|
|
|
"""Reload the automation from config."""
|
|
|
|
hass.services.call(DOMAIN, SERVICE_RELOAD)
|
|
|
|
|
|
|
|
|
2015-01-16 07:32:27 +00:00
|
|
|
def setup(hass, config):
|
2016-03-07 16:14:55 +00:00
|
|
|
"""Setup the automation."""
|
2016-10-05 04:20:48 +00:00
|
|
|
component = EntityComponent(_LOGGER, DOMAIN, hass,
|
|
|
|
group_name=GROUP_NAME_ALL_AUTOMATIONS)
|
2016-08-26 06:25:57 +00:00
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
success = run_coroutine_threadsafe(
|
|
|
|
_async_process_config(hass, config, component), hass.loop).result()
|
2015-01-16 07:32:27 +00:00
|
|
|
|
2016-08-26 06:25:57 +00:00
|
|
|
if not success:
|
|
|
|
return False
|
2015-09-14 05:25:42 +00:00
|
|
|
|
2016-09-04 15:15:52 +00:00
|
|
|
descriptions = conf_util.load_yaml_config_file(
|
|
|
|
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
|
|
|
|
2016-10-16 16:35:46 +00:00
|
|
|
@callback
|
2016-08-26 06:25:57 +00:00
|
|
|
def trigger_service_handler(service_call):
|
|
|
|
"""Handle automation triggers."""
|
2016-10-16 16:35:46 +00:00
|
|
|
for entity in component.async_extract_from_service(service_call):
|
2016-10-04 05:39:27 +00:00
|
|
|
hass.loop.create_task(entity.async_trigger(
|
|
|
|
service_call.data.get(ATTR_VARIABLES), True))
|
2015-09-14 07:02:33 +00:00
|
|
|
|
2016-10-16 16:35:46 +00:00
|
|
|
@callback
|
2016-10-04 05:39:27 +00:00
|
|
|
def turn_onoff_service_handler(service_call):
|
|
|
|
"""Handle automation turn on/off service calls."""
|
2016-10-01 08:22:13 +00:00
|
|
|
method = 'async_{}'.format(service_call.service)
|
2016-10-16 16:35:46 +00:00
|
|
|
for entity in component.async_extract_from_service(service_call):
|
2016-10-04 05:39:27 +00:00
|
|
|
hass.loop.create_task(getattr(entity, method)())
|
|
|
|
|
2016-10-16 16:35:46 +00:00
|
|
|
@callback
|
2016-10-04 05:39:27 +00:00
|
|
|
def toggle_service_handler(service_call):
|
|
|
|
"""Handle automation toggle service calls."""
|
2016-10-16 16:35:46 +00:00
|
|
|
for entity in component.async_extract_from_service(service_call):
|
2016-10-04 05:39:27 +00:00
|
|
|
if entity.is_on:
|
|
|
|
hass.loop.create_task(entity.async_turn_off())
|
|
|
|
else:
|
|
|
|
hass.loop.create_task(entity.async_turn_on())
|
2015-09-14 05:25:42 +00:00
|
|
|
|
2016-10-01 22:42:17 +00:00
|
|
|
@asyncio.coroutine
|
2016-09-04 15:15:52 +00:00
|
|
|
def reload_service_handler(service_call):
|
|
|
|
"""Remove all automations and load new ones from config."""
|
2016-10-16 16:35:46 +00:00
|
|
|
conf = yield from component.async_prepare_reload()
|
2016-09-04 15:15:52 +00:00
|
|
|
if conf is None:
|
|
|
|
return
|
2016-10-04 05:39:27 +00:00
|
|
|
hass.loop.create_task(_async_process_config(hass, conf, component))
|
2016-09-04 15:15:52 +00:00
|
|
|
|
2016-08-26 06:25:57 +00:00
|
|
|
hass.services.register(DOMAIN, SERVICE_TRIGGER, trigger_service_handler,
|
2016-09-04 15:15:52 +00:00
|
|
|
descriptions.get(SERVICE_TRIGGER),
|
2016-08-26 06:25:57 +00:00
|
|
|
schema=TRIGGER_SERVICE_SCHEMA)
|
2015-01-16 07:32:27 +00:00
|
|
|
|
2016-09-04 15:15:52 +00:00
|
|
|
hass.services.register(DOMAIN, SERVICE_RELOAD, reload_service_handler,
|
|
|
|
descriptions.get(SERVICE_RELOAD),
|
|
|
|
schema=RELOAD_SERVICE_SCHEMA)
|
|
|
|
|
2016-10-04 05:39:27 +00:00
|
|
|
hass.services.register(DOMAIN, SERVICE_TOGGLE, toggle_service_handler,
|
|
|
|
descriptions.get(SERVICE_TOGGLE),
|
|
|
|
schema=SERVICE_SCHEMA)
|
|
|
|
|
|
|
|
for service in (SERVICE_TURN_ON, SERVICE_TURN_OFF):
|
|
|
|
hass.services.register(DOMAIN, service, turn_onoff_service_handler,
|
2016-09-04 15:15:52 +00:00
|
|
|
descriptions.get(service),
|
2016-08-26 06:25:57 +00:00
|
|
|
schema=SERVICE_SCHEMA)
|
2015-01-16 07:32:27 +00:00
|
|
|
|
2015-09-15 05:05:40 +00:00
|
|
|
return True
|
2015-01-16 07:32:27 +00:00
|
|
|
|
|
|
|
|
2016-08-26 06:25:57 +00:00
|
|
|
class AutomationEntity(ToggleEntity):
|
|
|
|
"""Entity to show status of entity."""
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
# pylint: disable=abstract-method
|
2016-09-20 06:39:07 +00:00
|
|
|
# pylint: disable=too-many-arguments, too-many-instance-attributes
|
2016-10-01 08:22:13 +00:00
|
|
|
def __init__(self, name, async_attach_triggers, cond_func, async_action,
|
|
|
|
hidden):
|
2016-08-26 06:25:57 +00:00
|
|
|
"""Initialize an automation entity."""
|
|
|
|
self._name = name
|
2016-10-01 08:22:13 +00:00
|
|
|
self._async_attach_triggers = async_attach_triggers
|
2016-10-01 21:11:07 +00:00
|
|
|
self._async_detach_triggers = None
|
2016-08-26 06:25:57 +00:00
|
|
|
self._cond_func = cond_func
|
2016-10-01 08:22:13 +00:00
|
|
|
self._async_action = async_action
|
2016-10-01 21:11:07 +00:00
|
|
|
self._enabled = False
|
2016-08-26 06:25:57 +00:00
|
|
|
self._last_triggered = None
|
2016-09-20 06:39:07 +00:00
|
|
|
self._hidden = hidden
|
2016-08-26 06:25:57 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Name of the automation."""
|
|
|
|
return self._name
|
|
|
|
|
|
|
|
@property
|
|
|
|
def should_poll(self):
|
|
|
|
"""No polling needed for automation entities."""
|
|
|
|
return False
|
|
|
|
|
|
|
|
@property
|
|
|
|
def state_attributes(self):
|
|
|
|
"""Return the entity state attributes."""
|
|
|
|
return {
|
|
|
|
ATTR_LAST_TRIGGERED: self._last_triggered
|
|
|
|
}
|
|
|
|
|
2016-09-20 06:39:07 +00:00
|
|
|
@property
|
|
|
|
def hidden(self) -> bool:
|
|
|
|
"""Return True if the automation entity should be hidden from UIs."""
|
|
|
|
return self._hidden
|
|
|
|
|
2016-08-26 06:25:57 +00:00
|
|
|
@property
|
|
|
|
def is_on(self) -> bool:
|
|
|
|
"""Return True if entity is on."""
|
|
|
|
return self._enabled
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def async_turn_on(self, **kwargs) -> None:
|
2016-10-01 21:11:07 +00:00
|
|
|
"""Turn the entity on and update the state."""
|
2016-10-04 05:39:27 +00:00
|
|
|
if self._enabled:
|
|
|
|
return
|
|
|
|
|
2016-10-01 21:11:07 +00:00
|
|
|
yield from self.async_enable()
|
2016-10-04 05:39:27 +00:00
|
|
|
self.hass.loop.create_task(self.async_update_ha_state())
|
2016-08-26 06:25:57 +00:00
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def async_turn_off(self, **kwargs) -> None:
|
2016-08-26 06:25:57 +00:00
|
|
|
"""Turn the entity off."""
|
|
|
|
if not self._enabled:
|
|
|
|
return
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
self._async_detach_triggers()
|
|
|
|
self._async_detach_triggers = None
|
2016-08-26 06:25:57 +00:00
|
|
|
self._enabled = False
|
2016-10-16 16:35:46 +00:00
|
|
|
# It's important that the update is finished before this method
|
|
|
|
# ends because async_remove depends on it.
|
|
|
|
yield from self.async_update_ha_state()
|
2016-10-01 08:22:13 +00:00
|
|
|
|
|
|
|
@asyncio.coroutine
|
2016-10-04 05:39:27 +00:00
|
|
|
def async_trigger(self, variables, skip_condition=False):
|
|
|
|
"""Trigger automation.
|
2016-08-26 06:25:57 +00:00
|
|
|
|
2016-10-04 05:39:27 +00:00
|
|
|
This method is a coroutine.
|
|
|
|
"""
|
|
|
|
if skip_condition or self._cond_func(variables):
|
2016-10-19 01:11:35 +00:00
|
|
|
yield from self._async_action(self.entity_id, variables)
|
2016-08-26 06:25:57 +00:00
|
|
|
self._last_triggered = utcnow()
|
2016-10-04 05:39:27 +00:00
|
|
|
self.hass.loop.create_task(self.async_update_ha_state())
|
2016-08-26 06:25:57 +00:00
|
|
|
|
2016-10-16 16:35:46 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def async_remove(self):
|
2016-09-04 15:15:52 +00:00
|
|
|
"""Remove automation from HASS."""
|
2016-10-16 16:35:46 +00:00
|
|
|
yield from self.async_turn_off()
|
|
|
|
yield from super().async_remove()
|
2016-09-04 15:15:52 +00:00
|
|
|
|
2016-10-01 21:11:07 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def async_enable(self):
|
2016-10-04 05:39:27 +00:00
|
|
|
"""Enable this automation entity.
|
|
|
|
|
|
|
|
This method is a coroutine.
|
|
|
|
"""
|
2016-10-01 21:11:07 +00:00
|
|
|
if self._enabled:
|
|
|
|
return
|
|
|
|
|
|
|
|
self._async_detach_triggers = yield from self._async_attach_triggers(
|
|
|
|
self.async_trigger)
|
|
|
|
self._enabled = True
|
|
|
|
|
2016-09-04 15:15:52 +00:00
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
@asyncio.coroutine
|
|
|
|
def _async_process_config(hass, config, component):
|
2016-10-04 05:39:27 +00:00
|
|
|
"""Process config and add automations.
|
|
|
|
|
|
|
|
This method is a coroutine.
|
|
|
|
"""
|
2016-10-01 16:19:20 +00:00
|
|
|
entities = []
|
2016-10-04 05:39:27 +00:00
|
|
|
tasks = []
|
2016-09-04 15:15:52 +00:00
|
|
|
|
|
|
|
for config_key in extract_domain_configs(config, DOMAIN):
|
|
|
|
conf = config[config_key]
|
|
|
|
|
|
|
|
for list_no, config_block in enumerate(conf):
|
|
|
|
name = config_block.get(CONF_ALIAS) or "{} {}".format(config_key,
|
|
|
|
list_no)
|
|
|
|
|
2016-09-20 06:39:07 +00:00
|
|
|
hidden = config_block[CONF_HIDE_ENTITY]
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
action = _async_get_action(hass, config_block.get(CONF_ACTION, {}),
|
|
|
|
name)
|
2016-09-04 15:15:52 +00:00
|
|
|
|
|
|
|
if CONF_CONDITION in config_block:
|
2016-10-01 08:22:13 +00:00
|
|
|
cond_func = _async_process_if(hass, config, config_block)
|
2016-09-04 15:15:52 +00:00
|
|
|
|
|
|
|
if cond_func is None:
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
def cond_func(variables):
|
|
|
|
"""Condition will always pass."""
|
|
|
|
return True
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
async_attach_triggers = partial(
|
|
|
|
_async_process_trigger, hass, config,
|
|
|
|
config_block.get(CONF_TRIGGER, []), name)
|
2016-10-01 21:11:07 +00:00
|
|
|
entity = AutomationEntity(name, async_attach_triggers, cond_func,
|
|
|
|
action, hidden)
|
2016-10-04 06:41:08 +00:00
|
|
|
if config_block[CONF_INITIAL_STATE]:
|
2016-10-16 16:35:46 +00:00
|
|
|
tasks.append(entity.async_enable())
|
2016-10-01 21:11:07 +00:00
|
|
|
entities.append(entity)
|
2016-09-04 15:15:52 +00:00
|
|
|
|
2016-10-04 05:39:27 +00:00
|
|
|
yield from asyncio.gather(*tasks, loop=hass.loop)
|
2016-10-16 16:35:46 +00:00
|
|
|
hass.loop.create_task(component.async_add_entities(entities))
|
2016-10-01 16:19:20 +00:00
|
|
|
|
|
|
|
return len(entities) > 0
|
2016-09-04 15:15:52 +00:00
|
|
|
|
2016-08-26 06:25:57 +00:00
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
def _async_get_action(hass, config, name):
|
2016-03-07 16:14:55 +00:00
|
|
|
"""Return an action based on a configuration."""
|
2016-04-22 02:36:14 +00:00
|
|
|
script_obj = script.Script(hass, config, name)
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
@asyncio.coroutine
|
2016-10-19 01:11:35 +00:00
|
|
|
def action(entity_id, variables):
|
2016-03-07 16:14:55 +00:00
|
|
|
"""Action to be executed."""
|
2015-09-14 07:02:33 +00:00
|
|
|
_LOGGER.info('Executing %s', name)
|
2016-10-19 01:11:35 +00:00
|
|
|
logbook.async_log_entry(
|
|
|
|
hass, name, 'has been triggered', DOMAIN, entity_id)
|
2016-10-04 05:39:27 +00:00
|
|
|
hass.loop.create_task(script_obj.async_run(variables))
|
2015-01-16 07:32:27 +00:00
|
|
|
|
|
|
|
return action
|
2015-09-14 05:25:42 +00:00
|
|
|
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
def _async_process_if(hass, config, p_config):
|
2016-03-07 19:20:07 +00:00
|
|
|
"""Process if checks."""
|
2015-09-15 15:56:06 +00:00
|
|
|
if_configs = p_config.get(CONF_CONDITION)
|
|
|
|
|
2015-09-15 05:51:28 +00:00
|
|
|
checks = []
|
2015-09-14 05:25:42 +00:00
|
|
|
for if_config in if_configs:
|
2016-04-28 10:03:57 +00:00
|
|
|
try:
|
2016-10-01 08:22:13 +00:00
|
|
|
checks.append(condition.async_from_config(if_config, False))
|
2016-04-28 10:03:57 +00:00
|
|
|
except HomeAssistantError as ex:
|
2016-10-01 08:22:13 +00:00
|
|
|
_LOGGER.warning('Invalid condition: %s', ex)
|
|
|
|
return None
|
|
|
|
|
|
|
|
def if_action(variables=None):
|
|
|
|
"""AND all conditions."""
|
|
|
|
return all(check(hass, variables) for check in checks)
|
2015-09-15 05:51:28 +00:00
|
|
|
|
|
|
|
return if_action
|
2015-09-14 05:25:42 +00:00
|
|
|
|
2015-09-15 05:05:40 +00:00
|
|
|
|
2016-10-01 21:11:07 +00:00
|
|
|
@asyncio.coroutine
|
2016-10-01 08:22:13 +00:00
|
|
|
def _async_process_trigger(hass, config, trigger_configs, name, action):
|
2016-10-04 05:39:27 +00:00
|
|
|
"""Setup the triggers.
|
|
|
|
|
|
|
|
This method is a coroutine.
|
|
|
|
"""
|
2016-08-26 06:25:57 +00:00
|
|
|
removes = []
|
|
|
|
|
2015-09-15 05:05:40 +00:00
|
|
|
for conf in trigger_configs:
|
2016-10-01 21:11:07 +00:00
|
|
|
platform = yield from hass.loop.run_in_executor(
|
|
|
|
None, prepare_setup_platform, hass, config, DOMAIN,
|
|
|
|
conf.get(CONF_PLATFORM))
|
|
|
|
|
2015-09-15 05:05:40 +00:00
|
|
|
if platform is None:
|
2016-10-01 08:22:13 +00:00
|
|
|
return None
|
2015-09-14 05:25:42 +00:00
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
remove = platform.async_trigger(hass, conf, action)
|
2016-08-26 06:25:57 +00:00
|
|
|
|
|
|
|
if not remove:
|
2016-10-01 08:22:13 +00:00
|
|
|
_LOGGER.error("Error setting up trigger %s", name)
|
2016-08-26 06:25:57 +00:00
|
|
|
continue
|
|
|
|
|
2016-10-01 08:22:13 +00:00
|
|
|
_LOGGER.info("Initialized trigger %s", name)
|
2016-08-26 06:25:57 +00:00
|
|
|
removes.append(remove)
|
|
|
|
|
|
|
|
if not removes:
|
|
|
|
return None
|
|
|
|
|
|
|
|
def remove_triggers():
|
|
|
|
"""Remove attached triggers."""
|
|
|
|
for remove in removes:
|
|
|
|
remove()
|
|
|
|
|
|
|
|
return remove_triggers
|