diff --git a/homeassistant/components/demo.py b/homeassistant/components/demo.py index 3a70be00b38..1d391684465 100644 --- a/homeassistant/components/demo.py +++ b/homeassistant/components/demo.py @@ -95,18 +95,18 @@ def setup(hass, config): 'demo': { 'alias': 'Toggle {}'.format(lights[0].split('.')[1]), 'sequence': [{ - 'execute_service': 'light.turn_off', - 'service_data': {ATTR_ENTITY_ID: lights[0]} + 'service': 'light.turn_off', + 'data': {ATTR_ENTITY_ID: lights[0]} }, { 'delay': {'seconds': 5} }, { - 'execute_service': 'light.turn_on', - 'service_data': {ATTR_ENTITY_ID: lights[0]} + 'service': 'light.turn_on', + 'data': {ATTR_ENTITY_ID: lights[0]} }, { 'delay': {'seconds': 5} }, { - 'execute_service': 'light.turn_off', - 'service_data': {ATTR_ENTITY_ID: lights[0]} + 'service': 'light.turn_off', + 'data': {ATTR_ENTITY_ID: lights[0]} }] }}}) diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index 229a2a79e4d..6f955dd71a3 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -123,7 +123,7 @@ MEDIA_PLAYER_SCHEMA = vol.Schema({ }) MEDIA_PLAYER_MUTE_VOLUME_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({ - vol.Required(ATTR_MEDIA_VOLUME_MUTED): vol.Coerce(bool), + vol.Required(ATTR_MEDIA_VOLUME_MUTED): cv.boolean, }) MEDIA_PLAYER_SET_VOLUME_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({ diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index 31187940bd8..927b75024ab 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -72,8 +72,7 @@ MQTT_PUBLISH_SCHEMA = vol.Schema({ vol.Exclusive(ATTR_PAYLOAD_TEMPLATE, 'payload'): cv.string, vol.Required(ATTR_QOS, default=DEFAULT_QOS): vol.All(vol.Coerce(int), vol.In([0, 1, 2])), - # pylint: disable=no-value-for-parameter - vol.Required(ATTR_RETAIN, default=DEFAULT_RETAIN): vol.Boolean(), + vol.Required(ATTR_RETAIN, default=DEFAULT_RETAIN): cv.boolean, }, required=True) diff --git a/homeassistant/components/script.py b/homeassistant/components/script.py index cb5236ef1ec..28ebdbb5992 100644 --- a/homeassistant/components/script.py +++ b/homeassistant/components/script.py @@ -12,6 +12,8 @@ import threading from datetime import timedelta from itertools import islice +import voluptuous as vol + import homeassistant.util.dt as date_util from homeassistant.const import ( ATTR_ENTITY_ID, EVENT_TIME_CHANGED, SERVICE_TURN_OFF, SERVICE_TURN_ON, @@ -21,7 +23,7 @@ from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.event import track_point_in_utc_time from homeassistant.helpers.service import (call_from_config, validate_service_call) -from homeassistant.util import slugify +import homeassistant.helpers.config_validation as cv DOMAIN = "script" ENTITY_ID_FORMAT = DOMAIN + '.{}' @@ -42,6 +44,62 @@ ATTR_CAN_CANCEL = 'can_cancel' _LOGGER = logging.getLogger(__name__) +_ALIAS_VALIDATOR = vol.Schema(cv.string) + + +def _alias_stripper(validator): + """Strip alias from object for validation.""" + def validate(value): + """Validate without alias value.""" + value = value.copy() + alias = value.pop(CONF_ALIAS, None) + + if alias is not None: + alias = _ALIAS_VALIDATOR(alias) + + value = validator(value) + + if alias is not None: + value[CONF_ALIAS] = alias + + return value + + return validate + + +_DELAY_SCHEMA = { + vol.Required(CONF_DELAY): vol.All({ + CONF_ALIAS: cv.string, + 'days': vol.All(vol.Coerce(int), vol.Range(min=0)), + 'seconds': vol.All(vol.Coerce(int), vol.Range(min=0)), + 'microseconds': vol.All(vol.Coerce(int), vol.Range(min=0)), + 'milliseconds': vol.All(vol.Coerce(int), vol.Range(min=0)), + 'minutes': vol.All(vol.Coerce(int), vol.Range(min=0)), + 'hours': vol.All(vol.Coerce(int), vol.Range(min=0)), + 'weeks': vol.All(vol.Coerce(int), vol.Range(min=0)), + }, cv.has_at_least_one_key([ + 'days', 'seconds', 'microseconds', 'milliseconds', 'minutes', 'hours', + 'weeks'])) +} + +_EVENT_SCHEMA = cv.EVENT_SCHEMA.extend({ + CONF_ALIAS: cv.string, +}) + +_SCRIPT_ENTRY_SCHEMA = vol.Schema({ + CONF_ALIAS: cv.string, + vol.Required(CONF_SEQUENCE): vol.All(vol.Length(min=1), [vol.Any( + _EVENT_SCHEMA, + _DELAY_SCHEMA, + # Can't extend SERVICE_SCHEMA because it is an vol.All + _alias_stripper(cv.SERVICE_SCHEMA), + )]), +}) + +CONFIG_SCHEMA = vol.Schema({ + vol.Required(DOMAIN): cv.DictValidator(_SCRIPT_ENTRY_SCHEMA, cv.slug) +}, extra=vol.ALLOW_EXTRA) + def is_on(hass, entity_id): """Return if the switch is on based on the statemachine.""" @@ -73,22 +131,12 @@ def setup(hass, config): """Execute a service call to script.