RFC: Deprecate auto target all for services and introduce entity_id: * (#19006)
* Deprecate auto target all * Match on word 'all'
This commit is contained in:
parent
56c7e78cf2
commit
8ea0a8d40b
24 changed files with 143 additions and 41 deletions
|
@ -25,7 +25,7 @@ ATTR_CHANGED_BY = 'changed_by'
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
|
|
||||||
ALARM_SERVICE_SCHEMA = vol.Schema({
|
ALARM_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Optional(ATTR_CODE): cv.string,
|
vol.Optional(ATTR_CODE): cv.string,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -94,11 +94,11 @@ PLATFORM_SCHEMA = vol.Schema({
|
||||||
})
|
})
|
||||||
|
|
||||||
SERVICE_SCHEMA = vol.Schema({
|
SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
TRIGGER_SERVICE_SCHEMA = vol.Schema({
|
TRIGGER_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Required(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Optional(ATTR_VARIABLES, default={}): dict,
|
vol.Optional(ATTR_VARIABLES, default={}): dict,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ FALLBACK_STREAM_INTERVAL = 1 # seconds
|
||||||
MIN_STREAM_INTERVAL = 0.5 # seconds
|
MIN_STREAM_INTERVAL = 0.5 # seconds
|
||||||
|
|
||||||
CAMERA_SERVICE_SCHEMA = vol.Schema({
|
CAMERA_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
CAMERA_SERVICE_SNAPSHOT = CAMERA_SERVICE_SCHEMA.extend({
|
CAMERA_SERVICE_SNAPSHOT = CAMERA_SERVICE_SCHEMA.extend({
|
||||||
|
|
|
@ -92,15 +92,15 @@ CONVERTIBLE_ATTRIBUTE = [
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
ON_OFF_SERVICE_SCHEMA = vol.Schema({
|
ON_OFF_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
SET_AWAY_MODE_SCHEMA = vol.Schema({
|
SET_AWAY_MODE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_AWAY_MODE): cv.boolean,
|
vol.Required(ATTR_AWAY_MODE): cv.boolean,
|
||||||
})
|
})
|
||||||
SET_AUX_HEAT_SCHEMA = vol.Schema({
|
SET_AUX_HEAT_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_AUX_HEAT): cv.boolean,
|
vol.Required(ATTR_AUX_HEAT): cv.boolean,
|
||||||
})
|
})
|
||||||
SET_TEMPERATURE_SCHEMA = vol.Schema(vol.All(
|
SET_TEMPERATURE_SCHEMA = vol.Schema(vol.All(
|
||||||
|
@ -110,28 +110,28 @@ SET_TEMPERATURE_SCHEMA = vol.Schema(vol.All(
|
||||||
vol.Exclusive(ATTR_TEMPERATURE, 'temperature'): vol.Coerce(float),
|
vol.Exclusive(ATTR_TEMPERATURE, 'temperature'): vol.Coerce(float),
|
||||||
vol.Inclusive(ATTR_TARGET_TEMP_HIGH, 'temperature'): vol.Coerce(float),
|
vol.Inclusive(ATTR_TARGET_TEMP_HIGH, 'temperature'): vol.Coerce(float),
|
||||||
vol.Inclusive(ATTR_TARGET_TEMP_LOW, 'temperature'): vol.Coerce(float),
|
vol.Inclusive(ATTR_TARGET_TEMP_LOW, 'temperature'): vol.Coerce(float),
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Optional(ATTR_OPERATION_MODE): cv.string,
|
vol.Optional(ATTR_OPERATION_MODE): cv.string,
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
SET_FAN_MODE_SCHEMA = vol.Schema({
|
SET_FAN_MODE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_FAN_MODE): cv.string,
|
vol.Required(ATTR_FAN_MODE): cv.string,
|
||||||
})
|
})
|
||||||
SET_HOLD_MODE_SCHEMA = vol.Schema({
|
SET_HOLD_MODE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_HOLD_MODE): cv.string,
|
vol.Required(ATTR_HOLD_MODE): cv.string,
|
||||||
})
|
})
|
||||||
SET_OPERATION_MODE_SCHEMA = vol.Schema({
|
SET_OPERATION_MODE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_OPERATION_MODE): cv.string,
|
vol.Required(ATTR_OPERATION_MODE): cv.string,
|
||||||
})
|
})
|
||||||
SET_HUMIDITY_SCHEMA = vol.Schema({
|
SET_HUMIDITY_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_HUMIDITY): vol.Coerce(float),
|
vol.Required(ATTR_HUMIDITY): vol.Coerce(float),
|
||||||
})
|
})
|
||||||
SET_SWING_MODE_SCHEMA = vol.Schema({
|
SET_SWING_MODE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_SWING_MODE): cv.string,
|
vol.Required(ATTR_SWING_MODE): cv.string,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ SERVICE_INCREMENT = 'increment'
|
||||||
SERVICE_RESET = 'reset'
|
SERVICE_RESET = 'reset'
|
||||||
|
|
||||||
SERVICE_SCHEMA = vol.Schema({
|
SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
|
|
|
@ -60,7 +60,7 @@ INTENT_OPEN_COVER = 'HassOpenCover'
|
||||||
INTENT_CLOSE_COVER = 'HassCloseCover'
|
INTENT_CLOSE_COVER = 'HassCloseCover'
|
||||||
|
|
||||||
COVER_SERVICE_SCHEMA = vol.Schema({
|
COVER_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
COVER_SET_COVER_POSITION_SCHEMA = COVER_SERVICE_SCHEMA.extend({
|
COVER_SET_COVER_POSITION_SCHEMA = COVER_SERVICE_SCHEMA.extend({
|
||||||
|
|
|
@ -61,30 +61,30 @@ PROP_TO_ATTR = {
|
||||||
} # type: dict
|
} # type: dict
|
||||||
|
|
||||||
FAN_SET_SPEED_SCHEMA = vol.Schema({
|
FAN_SET_SPEED_SCHEMA = vol.Schema({
|
||||||
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Required(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_SPEED): cv.string
|
vol.Required(ATTR_SPEED): cv.string
|
||||||
}) # type: dict
|
}) # type: dict
|
||||||
|
|
||||||
FAN_TURN_ON_SCHEMA = vol.Schema({
|
FAN_TURN_ON_SCHEMA = vol.Schema({
|
||||||
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Required(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Optional(ATTR_SPEED): cv.string
|
vol.Optional(ATTR_SPEED): cv.string
|
||||||
}) # type: dict
|
}) # type: dict
|
||||||
|
|
||||||
FAN_TURN_OFF_SCHEMA = vol.Schema({
|
FAN_TURN_OFF_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids
|
||||||
}) # type: dict
|
}) # type: dict
|
||||||
|
|
||||||
FAN_OSCILLATE_SCHEMA = vol.Schema({
|
FAN_OSCILLATE_SCHEMA = vol.Schema({
|
||||||
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Required(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_OSCILLATING): cv.boolean
|
vol.Required(ATTR_OSCILLATING): cv.boolean
|
||||||
}) # type: dict
|
}) # type: dict
|
||||||
|
|
||||||
FAN_TOGGLE_SCHEMA = vol.Schema({
|
FAN_TOGGLE_SCHEMA = vol.Schema({
|
||||||
vol.Required(ATTR_ENTITY_ID): cv.entity_ids
|
vol.Required(ATTR_ENTITY_ID): cv.comp_entity_ids
|
||||||
})
|
})
|
||||||
|
|
||||||
FAN_SET_DIRECTION_SCHEMA = vol.Schema({
|
FAN_SET_DIRECTION_SCHEMA = vol.Schema({
|
||||||
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Required(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Optional(ATTR_DIRECTION): cv.string
|
vol.Optional(ATTR_DIRECTION): cv.string
|
||||||
}) # type: dict
|
}) # type: dict
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ SERVICE_REMOVE = 'remove'
|
||||||
CONTROL_TYPES = vol.In(['hidden', None])
|
CONTROL_TYPES = vol.In(['hidden', None])
|
||||||
|
|
||||||
SET_VISIBILITY_SERVICE_SCHEMA = vol.Schema({
|
SET_VISIBILITY_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_VISIBLE): cv.boolean
|
vol.Required(ATTR_VISIBLE): cv.boolean
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
|
||||||
})
|
})
|
||||||
|
|
||||||
SERVICE_SCAN_SCHEMA = vol.Schema({
|
SERVICE_SCAN_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ VALID_BRIGHTNESS = vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255))
|
||||||
VALID_BRIGHTNESS_PCT = vol.All(vol.Coerce(float), vol.Range(min=0, max=100))
|
VALID_BRIGHTNESS_PCT = vol.All(vol.Coerce(float), vol.Range(min=0, max=100))
|
||||||
|
|
||||||
LIGHT_TURN_ON_SCHEMA = vol.Schema({
|
LIGHT_TURN_ON_SCHEMA = vol.Schema({
|
||||||
ATTR_ENTITY_ID: cv.entity_ids,
|
ATTR_ENTITY_ID: cv.comp_entity_ids,
|
||||||
vol.Exclusive(ATTR_PROFILE, COLOR_GROUP): cv.string,
|
vol.Exclusive(ATTR_PROFILE, COLOR_GROUP): cv.string,
|
||||||
ATTR_TRANSITION: VALID_TRANSITION,
|
ATTR_TRANSITION: VALID_TRANSITION,
|
||||||
ATTR_BRIGHTNESS: VALID_BRIGHTNESS,
|
ATTR_BRIGHTNESS: VALID_BRIGHTNESS,
|
||||||
|
@ -115,13 +115,13 @@ LIGHT_TURN_ON_SCHEMA = vol.Schema({
|
||||||
})
|
})
|
||||||
|
|
||||||
LIGHT_TURN_OFF_SCHEMA = vol.Schema({
|
LIGHT_TURN_OFF_SCHEMA = vol.Schema({
|
||||||
ATTR_ENTITY_ID: cv.entity_ids,
|
ATTR_ENTITY_ID: cv.comp_entity_ids,
|
||||||
ATTR_TRANSITION: VALID_TRANSITION,
|
ATTR_TRANSITION: VALID_TRANSITION,
|
||||||
ATTR_FLASH: vol.In([FLASH_SHORT, FLASH_LONG]),
|
ATTR_FLASH: vol.In([FLASH_SHORT, FLASH_LONG]),
|
||||||
})
|
})
|
||||||
|
|
||||||
LIGHT_TOGGLE_SCHEMA = vol.Schema({
|
LIGHT_TOGGLE_SCHEMA = vol.Schema({
|
||||||
ATTR_ENTITY_ID: cv.entity_ids,
|
ATTR_ENTITY_ID: cv.comp_entity_ids,
|
||||||
ATTR_TRANSITION: VALID_TRANSITION,
|
ATTR_TRANSITION: VALID_TRANSITION,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ GROUP_NAME_ALL_LOCKS = 'all locks'
|
||||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||||
|
|
||||||
LOCK_SERVICE_SCHEMA = vol.Schema({
|
LOCK_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Optional(ATTR_CODE): cv.string,
|
vol.Optional(ATTR_CODE): cv.string,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ SUPPORT_SELECT_SOUND_MODE = 65536
|
||||||
|
|
||||||
# Service call validation schemas
|
# Service call validation schemas
|
||||||
MEDIA_PLAYER_SCHEMA = vol.Schema({
|
MEDIA_PLAYER_SCHEMA = vol.Schema({
|
||||||
ATTR_ENTITY_ID: cv.entity_ids,
|
ATTR_ENTITY_ID: cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
MEDIA_PLAYER_SET_VOLUME_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
|
MEDIA_PLAYER_SET_VOLUME_SCHEMA = MEDIA_PLAYER_SCHEMA.extend({
|
||||||
|
|
|
@ -46,7 +46,7 @@ DEFAULT_NUM_REPEATS = 1
|
||||||
DEFAULT_DELAY_SECS = 0.4
|
DEFAULT_DELAY_SECS = 0.4
|
||||||
|
|
||||||
REMOTE_SERVICE_SCHEMA = vol.Schema({
|
REMOTE_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
REMOTE_SERVICE_ACTIVITY_SCHEMA = REMOTE_SERVICE_SCHEMA.extend({
|
REMOTE_SERVICE_ACTIVITY_SCHEMA = REMOTE_SERVICE_SCHEMA.extend({
|
||||||
|
|
|
@ -56,7 +56,7 @@ PLATFORM_SCHEMA = vol.Schema(
|
||||||
), extra=vol.ALLOW_EXTRA)
|
), extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
SCENE_SERVICE_SCHEMA = vol.Schema({
|
SCENE_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ PROP_TO_ATTR = {
|
||||||
}
|
}
|
||||||
|
|
||||||
SWITCH_SERVICE_SCHEMA = vol.Schema({
|
SWITCH_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
|
@ -49,7 +49,7 @@ SERVICE_PAUSE = 'pause'
|
||||||
SERVICE_STOP = 'stop'
|
SERVICE_STOP = 'stop'
|
||||||
|
|
||||||
VACUUM_SERVICE_SCHEMA = vol.Schema({
|
VACUUM_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
VACUUM_SET_FAN_SPEED_SERVICE_SCHEMA = VACUUM_SERVICE_SCHEMA.extend({
|
VACUUM_SET_FAN_SPEED_SERVICE_SCHEMA = VACUUM_SERVICE_SCHEMA.extend({
|
||||||
|
|
|
@ -57,22 +57,22 @@ CONVERTIBLE_ATTRIBUTE = [
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
ON_OFF_SERVICE_SCHEMA = vol.Schema({
|
ON_OFF_SERVICE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
})
|
})
|
||||||
|
|
||||||
SET_AWAY_MODE_SCHEMA = vol.Schema({
|
SET_AWAY_MODE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_AWAY_MODE): cv.boolean,
|
vol.Required(ATTR_AWAY_MODE): cv.boolean,
|
||||||
})
|
})
|
||||||
SET_TEMPERATURE_SCHEMA = vol.Schema(vol.All(
|
SET_TEMPERATURE_SCHEMA = vol.Schema(vol.All(
|
||||||
{
|
{
|
||||||
vol.Required(ATTR_TEMPERATURE, 'temperature'): vol.Coerce(float),
|
vol.Required(ATTR_TEMPERATURE, 'temperature'): vol.Coerce(float),
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Optional(ATTR_OPERATION_MODE): cv.string,
|
vol.Optional(ATTR_OPERATION_MODE): cv.string,
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
SET_OPERATION_MODE_SCHEMA = vol.Schema({
|
SET_OPERATION_MODE_SCHEMA = vol.Schema({
|
||||||
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
vol.Optional(ATTR_ENTITY_ID): cv.comp_entity_ids,
|
||||||
vol.Required(ATTR_OPERATION_MODE): cv.string,
|
vol.Required(ATTR_OPERATION_MODE): cv.string,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,9 @@ PLATFORM_FORMAT = '{}.{}'
|
||||||
# Can be used to specify a catch all when registering state or event listeners.
|
# Can be used to specify a catch all when registering state or event listeners.
|
||||||
MATCH_ALL = '*'
|
MATCH_ALL = '*'
|
||||||
|
|
||||||
|
# Entity target all constant
|
||||||
|
ENTITY_MATCH_ALL = 'all'
|
||||||
|
|
||||||
# If no name is specified
|
# If no name is specified
|
||||||
DEVICE_DEFAULT_NAME = 'Unnamed Device'
|
DEVICE_DEFAULT_NAME = 'Unnamed Device'
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ from homeassistant.const import (
|
||||||
CONF_PLATFORM, CONF_SCAN_INTERVAL, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
CONF_PLATFORM, CONF_SCAN_INTERVAL, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
||||||
CONF_ALIAS, CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, WEEKDAYS,
|
CONF_ALIAS, CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, WEEKDAYS,
|
||||||
CONF_CONDITION, CONF_BELOW, CONF_ABOVE, CONF_TIMEOUT, SUN_EVENT_SUNSET,
|
CONF_CONDITION, CONF_BELOW, CONF_ABOVE, CONF_TIMEOUT, SUN_EVENT_SUNSET,
|
||||||
SUN_EVENT_SUNRISE, CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC)
|
SUN_EVENT_SUNRISE, CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC,
|
||||||
|
ENTITY_MATCH_ALL)
|
||||||
from homeassistant.core import valid_entity_id, split_entity_id
|
from homeassistant.core import valid_entity_id, split_entity_id
|
||||||
from homeassistant.exceptions import TemplateError
|
from homeassistant.exceptions import TemplateError
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
|
@ -161,6 +162,12 @@ def entity_ids(value: Union[str, Sequence]) -> Sequence[str]:
|
||||||
return [entity_id(ent_id) for ent_id in value]
|
return [entity_id(ent_id) for ent_id in value]
|
||||||
|
|
||||||
|
|
||||||
|
comp_entity_ids = vol.Any(
|
||||||
|
vol.All(vol.Lower, ENTITY_MATCH_ALL),
|
||||||
|
entity_ids
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def entity_domain(domain: str):
|
def entity_domain(domain: str):
|
||||||
"""Validate that entity belong to domain."""
|
"""Validate that entity belong to domain."""
|
||||||
def validate(value: Any) -> str:
|
def validate(value: Any) -> str:
|
||||||
|
|
|
@ -7,7 +7,7 @@ import logging
|
||||||
from homeassistant import config as conf_util
|
from homeassistant import config as conf_util
|
||||||
from homeassistant.setup import async_prepare_setup_platform
|
from homeassistant.setup import async_prepare_setup_platform
|
||||||
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, MATCH_ALL)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import config_per_platform, discovery
|
from homeassistant.helpers import config_per_platform, discovery
|
||||||
|
@ -161,7 +161,15 @@ class EntityComponent:
|
||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
"""
|
"""
|
||||||
if ATTR_ENTITY_ID not in service.data:
|
data_ent_id = service.data.get(ATTR_ENTITY_ID)
|
||||||
|
|
||||||
|
if data_ent_id in (None, MATCH_ALL):
|
||||||
|
if data_ent_id is None:
|
||||||
|
self.logger.warning(
|
||||||
|
'Not passing an entity ID to a service to target all '
|
||||||
|
'entities is deprecated. Update your call to %s.%s to be '
|
||||||
|
'instead: entity_id: "*"', service.domain, service.service)
|
||||||
|
|
||||||
return [entity for entity in self.entities if entity.available]
|
return [entity for entity in self.entities if entity.available]
|
||||||
|
|
||||||
entity_ids = set(extract_entity_ids(self.hass, service, expand_group))
|
entity_ids = set(extract_entity_ids(self.hass, service, expand_group))
|
||||||
|
|
|
@ -6,7 +6,7 @@ from os import path
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.auth.permissions.const import POLICY_CONTROL
|
from homeassistant.auth.permissions.const import POLICY_CONTROL
|
||||||
from homeassistant.const import ATTR_ENTITY_ID
|
from homeassistant.const import ATTR_ENTITY_ID, ENTITY_MATCH_ALL
|
||||||
import homeassistant.core as ha
|
import homeassistant.core as ha
|
||||||
from homeassistant.exceptions import TemplateError, Unauthorized, UnknownUser
|
from homeassistant.exceptions import TemplateError, Unauthorized, UnknownUser
|
||||||
from homeassistant.helpers import template
|
from homeassistant.helpers import template
|
||||||
|
@ -197,7 +197,12 @@ async def entity_service_call(hass, platforms, func, call):
|
||||||
entity_perms = None
|
entity_perms = None
|
||||||
|
|
||||||
# Are we trying to target all entities
|
# Are we trying to target all entities
|
||||||
target_all_entities = ATTR_ENTITY_ID not in call.data
|
if ATTR_ENTITY_ID in call.data:
|
||||||
|
target_all_entities = call.data[ATTR_ENTITY_ID] == ENTITY_MATCH_ALL
|
||||||
|
else:
|
||||||
|
_LOGGER.warning('Not passing an entity ID to a service to target all '
|
||||||
|
'entities is deprecated. Use instead: entity_id: "*"')
|
||||||
|
target_all_entities = True
|
||||||
|
|
||||||
if not target_all_entities:
|
if not target_all_entities:
|
||||||
# A set of entities we're trying to target.
|
# A set of entities we're trying to target.
|
||||||
|
|
|
@ -584,3 +584,16 @@ def test_is_regex():
|
||||||
|
|
||||||
valid_re = ".*"
|
valid_re = ".*"
|
||||||
schema(valid_re)
|
schema(valid_re)
|
||||||
|
|
||||||
|
|
||||||
|
def test_comp_entity_ids():
|
||||||
|
"""Test config validation for component entity IDs."""
|
||||||
|
schema = vol.Schema(cv.comp_entity_ids)
|
||||||
|
|
||||||
|
for valid in ('ALL', 'all', 'AlL', 'light.kitchen', ['light.kitchen'],
|
||||||
|
['light.kitchen', 'light.ceiling'], []):
|
||||||
|
schema(valid)
|
||||||
|
|
||||||
|
for invalid in (['light.kitchen', 'not-entity-id'], '*', ''):
|
||||||
|
with pytest.raises(vol.Invalid):
|
||||||
|
schema(invalid)
|
||||||
|
|
|
@ -452,3 +452,37 @@ async def test_set_service_race(hass):
|
||||||
|
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert not exception
|
assert not exception
|
||||||
|
|
||||||
|
|
||||||
|
async def test_extract_all_omit_entity_id(hass, caplog):
|
||||||
|
"""Test extract all with None and *."""
|
||||||
|
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||||
|
await component.async_add_entities([
|
||||||
|
MockEntity(name='test_1'),
|
||||||
|
MockEntity(name='test_2'),
|
||||||
|
])
|
||||||
|
|
||||||
|
call = ha.ServiceCall('test', 'service')
|
||||||
|
|
||||||
|
assert ['test_domain.test_1', 'test_domain.test_2'] == \
|
||||||
|
sorted(ent.entity_id for ent in
|
||||||
|
component.async_extract_from_service(call))
|
||||||
|
assert ('Not passing an entity ID to a service to target all entities is '
|
||||||
|
'deprecated') in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_extract_all_use_match_all(hass, caplog):
|
||||||
|
"""Test extract all with None and *."""
|
||||||
|
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||||
|
await component.async_add_entities([
|
||||||
|
MockEntity(name='test_1'),
|
||||||
|
MockEntity(name='test_2'),
|
||||||
|
])
|
||||||
|
|
||||||
|
call = ha.ServiceCall('test', 'service', {'entity_id': '*'})
|
||||||
|
|
||||||
|
assert ['test_domain.test_1', 'test_domain.test_2'] == \
|
||||||
|
sorted(ent.entity_id for ent in
|
||||||
|
component.async_extract_from_service(call))
|
||||||
|
assert ('Not passing an entity ID to a service to target all entities is '
|
||||||
|
'deprecated') not in caplog.text
|
||||||
|
|
|
@ -306,3 +306,35 @@ async def test_call_no_context_target_specific(
|
||||||
assert len(mock_service_platform_call.mock_calls) == 1
|
assert len(mock_service_platform_call.mock_calls) == 1
|
||||||
entities = mock_service_platform_call.mock_calls[0][1][2]
|
entities = mock_service_platform_call.mock_calls[0][1][2]
|
||||||
assert entities == [mock_entities['light.kitchen']]
|
assert entities == [mock_entities['light.kitchen']]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_call_with_match_all(hass, mock_service_platform_call,
|
||||||
|
mock_entities, caplog):
|
||||||
|
"""Check we only target allowed entities if targetting all."""
|
||||||
|
await service.entity_service_call(hass, [
|
||||||
|
Mock(entities=mock_entities)
|
||||||
|
], Mock(), ha.ServiceCall('test_domain', 'test_service', {
|
||||||
|
'entity_id': 'all'
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert len(mock_service_platform_call.mock_calls) == 1
|
||||||
|
entities = mock_service_platform_call.mock_calls[0][1][2]
|
||||||
|
assert entities == [
|
||||||
|
mock_entities['light.kitchen'], mock_entities['light.living_room']]
|
||||||
|
assert ('Not passing an entity ID to a service to target '
|
||||||
|
'all entities is deprecated') not in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_call_with_omit_entity_id(hass, mock_service_platform_call,
|
||||||
|
mock_entities, caplog):
|
||||||
|
"""Check we only target allowed entities if targetting all."""
|
||||||
|
await service.entity_service_call(hass, [
|
||||||
|
Mock(entities=mock_entities)
|
||||||
|
], Mock(), ha.ServiceCall('test_domain', 'test_service'))
|
||||||
|
|
||||||
|
assert len(mock_service_platform_call.mock_calls) == 1
|
||||||
|
entities = mock_service_platform_call.mock_calls[0][1][2]
|
||||||
|
assert entities == [
|
||||||
|
mock_entities['light.kitchen'], mock_entities['light.living_room']]
|
||||||
|
assert ('Not passing an entity ID to a service to target '
|
||||||
|
'all entities is deprecated') in caplog.text
|
||||||
|
|
Loading…
Add table
Reference in a new issue