1
mirror of https://github.com/home-assistant/core synced 2024-07-30 21:18:57 +02:00

Use templates in service calls

This commit is contained in:
Per Sandström 2016-03-10 21:36:05 +01:00
parent cfd65e48cb
commit 81e5a852f0
3 changed files with 78 additions and 8 deletions

View File

@ -11,13 +11,14 @@ from homeassistant.bootstrap import prepare_setup_platform
from homeassistant.const import CONF_PLATFORM
from homeassistant.components import logbook
from homeassistant.helpers.service import call_from_config
from homeassistant.helpers.service import validate_service_call
DOMAIN = 'automation'
DEPENDENCIES = ['group']
CONF_ALIAS = 'alias'
CONF_SERVICE = 'service'
CONF_CONDITION = 'condition'
CONF_ACTION = 'action'
@ -82,8 +83,9 @@ def _setup_automation(hass, config_block, name, config):
def _get_action(hass, config, name):
"""Return an action based on a configuration."""
if CONF_SERVICE not in config:
_LOGGER.error('Error setting up %s, no action specified.', name)
validation_error = validate_service_call(config)
if validation_error:
_LOGGER.error(validation_error)
return None
def action():

View File

@ -3,14 +3,16 @@ import functools
import logging
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.helpers.entity import split_entity_id
from homeassistant.helpers import template
from homeassistant.loader import get_component
HASS = None
CONF_SERVICE = 'service'
CONF_SERVICE_TEMPLATE = 'service_template'
CONF_SERVICE_ENTITY_ID = 'entity_id'
CONF_SERVICE_DATA = 'data'
CONF_SERVICE_DATA_TEMPLATE = 'data_template'
_LOGGER = logging.getLogger(__name__)
@ -29,14 +31,20 @@ def service(domain, service_name):
def call_from_config(hass, config, blocking=False):
"""Call a service based on a config hash."""
if not isinstance(config, dict) or CONF_SERVICE not in config:
_LOGGER.error('Missing key %s: %s', CONF_SERVICE, config)
validation_error = validate_service_call(config)
if validation_error:
_LOGGER.error(validation_error)
return
domain_service = (
config[CONF_SERVICE]
if CONF_SERVICE in config
else template.render(hass, config[CONF_SERVICE_TEMPLATE]))
try:
domain, service_name = split_entity_id(config[CONF_SERVICE])
domain, service_name = domain_service.split('.', 1)
except ValueError:
_LOGGER.error('Invalid service specified: %s', config[CONF_SERVICE])
_LOGGER.error('Invalid service specified: %s', domain_service)
return
service_data = config.get(CONF_SERVICE_DATA)
@ -49,6 +57,13 @@ def call_from_config(hass, config, blocking=False):
_LOGGER.error("%s should be a dictionary", CONF_SERVICE_DATA)
service_data = {}
service_data_template = config.get(CONF_SERVICE_DATA_TEMPLATE)
if service_data_template and isinstance(service_data_template, dict):
for key, value in service_data_template.items():
service_data[key] = template.render(hass, value)
elif service_data_template:
_LOGGER.error("%s should be a dictionary", CONF_SERVICE_DATA)
entity_id = config.get(CONF_SERVICE_ENTITY_ID)
if isinstance(entity_id, str):
service_data[ATTR_ENTITY_ID] = [ent.strip() for ent in
@ -76,3 +91,19 @@ def extract_entity_ids(hass, service_call):
return group.expand_entity_ids(hass, [service_ent_id])
return [ent_id for ent_id in group.expand_entity_ids(hass, service_ent_id)]
def validate_service_call(config):
"""Validate service call configuration.
Helper method to validate that a configuration is a valid service call.
Returns None if validation succeeds, else an error description
"""
if not isinstance(config, dict):
return 'Invalid configuration {}'.format(config)
if CONF_SERVICE not in config and CONF_SERVICE_TEMPLATE not in config:
return 'Missing key {} or {}: {}'.format(
CONF_SERVICE,
CONF_SERVICE_TEMPLATE,
config)
return None

View File

@ -39,6 +39,25 @@ class TestServiceHelpers(unittest.TestCase):
self.hass.pool.block_till_done()
self.assertEqual(1, len(runs))
def test_template_service_call(self):
""" Test service call with tempating. """
config = {
'service_template': '{{ \'test_domain.test_service\' }}',
'entity_id': 'hello.world',
'data_template': {
'hello': '{{ \'goodbye\' }}',
},
}
runs = []
decor = service.service('test_domain', 'test_service')
decor(lambda x, y: runs.append(y))
service.call_from_config(self.hass, config)
self.hass.pool.block_till_done()
self.assertEqual('goodbye', runs[0].data['hello'])
def test_split_entity_string(self):
service.call_from_config(self.hass, {
'service': 'test_domain.test_service',
@ -99,3 +118,21 @@ class TestServiceHelpers(unittest.TestCase):
self.assertEqual(['light.ceiling', 'light.kitchen'],
service.extract_entity_ids(self.hass, call))
def test_validate_service_call(self):
"""Test is_valid_service_call method"""
self.assertNotEqual(
service.validate_service_call(
{}),
None
)
self.assertEqual(
service.validate_service_call(
{'service': 'test_domain.test_service'}),
None
)
self.assertEqual(
service.validate_service_call(
{'service_template': 'test_domain.{{ \'test_service\' }}'}),
None
)