Do not select all entities when omitting entity ID in service call (#29178)
* Do not select all entities when omitting entity ID * Address comments Matthew * Require either area_id or entity_id * Fix tests * Fix test
This commit is contained in:
parent
9587afc5ce
commit
02d9ed5e36
47 changed files with 538 additions and 626 deletions
|
@ -17,7 +17,7 @@ from homeassistant.const import (
|
|||
)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
make_entity_service_schema,
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
)
|
||||
|
@ -41,9 +41,7 @@ ATTR_CODE_ARM_REQUIRED = "code_arm_required"
|
|||
|
||||
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||
|
||||
ALARM_SERVICE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Optional(ATTR_CODE): cv.string}
|
||||
)
|
||||
ALARM_SERVICE_SCHEMA = make_entity_service_schema({vol.Optional(ATTR_CODE): cv.string})
|
||||
|
||||
|
||||
async def async_setup(hass, config):
|
||||
|
|
|
@ -24,7 +24,7 @@ from homeassistant.core import Context, CoreState, HomeAssistant
|
|||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import condition, extract_domain_configs, script
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.config_validation import make_entity_service_schema
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
@ -106,7 +106,7 @@ PLATFORM_SCHEMA = vol.Schema(
|
|||
}
|
||||
)
|
||||
|
||||
TRIGGER_SERVICE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
TRIGGER_SERVICE_SCHEMA = make_entity_service_schema(
|
||||
{vol.Optional(ATTR_VARIABLES, default={}): dict}
|
||||
)
|
||||
|
||||
|
@ -184,12 +184,18 @@ async def async_setup(hass, config):
|
|||
)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_TOGGLE, toggle_service_handler, schema=ENTITY_SERVICE_SCHEMA
|
||||
DOMAIN,
|
||||
SERVICE_TOGGLE,
|
||||
toggle_service_handler,
|
||||
schema=make_entity_service_schema({}),
|
||||
)
|
||||
|
||||
for service in (SERVICE_TURN_ON, SERVICE_TURN_OFF):
|
||||
hass.services.async_register(
|
||||
DOMAIN, service, turn_onoff_service_handler, schema=ENTITY_SERVICE_SCHEMA
|
||||
DOMAIN,
|
||||
service,
|
||||
turn_onoff_service_handler,
|
||||
schema=make_entity_service_schema({}),
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -19,7 +19,7 @@ from homeassistant.const import (
|
|||
)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
make_entity_service_schema,
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
)
|
||||
|
@ -84,38 +84,19 @@ CONVERTIBLE_ATTRIBUTE = [ATTR_TEMPERATURE, ATTR_TARGET_TEMP_LOW, ATTR_TARGET_TEM
|
|||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SET_AUX_HEAT_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_AUX_HEAT): cv.boolean}
|
||||
)
|
||||
SET_TEMPERATURE_SCHEMA = vol.Schema(
|
||||
vol.All(
|
||||
cv.has_at_least_one_key(
|
||||
ATTR_TEMPERATURE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW
|
||||
),
|
||||
ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Exclusive(ATTR_TEMPERATURE, "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.Optional(ATTR_HVAC_MODE): vol.In(HVAC_MODES),
|
||||
}
|
||||
),
|
||||
)
|
||||
)
|
||||
SET_FAN_MODE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_FAN_MODE): cv.string}
|
||||
)
|
||||
SET_PRESET_MODE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_PRESET_MODE): cv.string}
|
||||
)
|
||||
SET_HVAC_MODE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_HVAC_MODE): vol.In(HVAC_MODES)}
|
||||
)
|
||||
SET_HUMIDITY_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_HUMIDITY): vol.Coerce(float)}
|
||||
)
|
||||
SET_SWING_MODE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_SWING_MODE): cv.string}
|
||||
|
||||
SET_TEMPERATURE_SCHEMA = vol.All(
|
||||
cv.has_at_least_one_key(
|
||||
ATTR_TEMPERATURE, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW
|
||||
),
|
||||
make_entity_service_schema(
|
||||
{
|
||||
vol.Exclusive(ATTR_TEMPERATURE, "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.Optional(ATTR_HVAC_MODE): vol.In(HVAC_MODES),
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
@ -126,32 +107,40 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
|
|||
)
|
||||
await component.async_setup(config)
|
||||
|
||||
component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_turn_on")
|
||||
component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off")
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_ON, ENTITY_SERVICE_SCHEMA, "async_turn_on"
|
||||
SERVICE_SET_HVAC_MODE,
|
||||
{vol.Required(ATTR_HVAC_MODE): vol.In(HVAC_MODES)},
|
||||
"async_set_hvac_mode",
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, ENTITY_SERVICE_SCHEMA, "async_turn_off"
|
||||
SERVICE_SET_PRESET_MODE,
|
||||
{vol.Required(ATTR_PRESET_MODE): cv.string},
|
||||
"async_set_preset_mode",
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_HVAC_MODE, SET_HVAC_MODE_SCHEMA, "async_set_hvac_mode"
|
||||
SERVICE_SET_AUX_HEAT,
|
||||
{vol.Required(ATTR_AUX_HEAT): cv.boolean},
|
||||
async_service_aux_heat,
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_PRESET_MODE, SET_PRESET_MODE_SCHEMA, "async_set_preset_mode"
|
||||
SERVICE_SET_TEMPERATURE, SET_TEMPERATURE_SCHEMA, async_service_temperature_set,
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_AUX_HEAT, SET_AUX_HEAT_SCHEMA, async_service_aux_heat
|
||||
SERVICE_SET_HUMIDITY,
|
||||
{vol.Required(ATTR_HUMIDITY): vol.Coerce(float)},
|
||||
"async_set_humidity",
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_TEMPERATURE, SET_TEMPERATURE_SCHEMA, async_service_temperature_set
|
||||
SERVICE_SET_FAN_MODE,
|
||||
{vol.Required(ATTR_FAN_MODE): cv.string},
|
||||
"async_set_fan_mode",
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_HUMIDITY, SET_HUMIDITY_SCHEMA, "async_set_humidity"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_FAN_MODE, SET_FAN_MODE_SCHEMA, "async_set_fan_mode"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_SWING_MODE, SET_SWING_MODE_SCHEMA, "async_set_swing_mode"
|
||||
SERVICE_SET_SWING_MODE,
|
||||
{vol.Required(ATTR_SWING_MODE): cv.string},
|
||||
"async_set_swing_mode",
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -6,7 +6,6 @@ import voluptuous as vol
|
|||
from homeassistant.const import CONF_ICON, CONF_NAME, CONF_MAXIMUM, CONF_MINIMUM
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
|
@ -33,15 +32,6 @@ SERVICE_INCREMENT = "increment"
|
|||
SERVICE_RESET = "reset"
|
||||
SERVICE_CONFIGURE = "configure"
|
||||
|
||||
SERVICE_SCHEMA_CONFIGURE = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional(ATTR_MINIMUM): vol.Any(None, vol.Coerce(int)),
|
||||
vol.Optional(ATTR_MAXIMUM): vol.Any(None, vol.Coerce(int)),
|
||||
vol.Optional(ATTR_STEP): cv.positive_int,
|
||||
vol.Optional(ATTR_INITIAL): cv.positive_int,
|
||||
vol.Optional(VALUE): cv.positive_int,
|
||||
}
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
|
@ -95,17 +85,19 @@ async def async_setup(hass, config):
|
|||
if not entities:
|
||||
return False
|
||||
|
||||
component.async_register_entity_service(SERVICE_INCREMENT, {}, "async_increment")
|
||||
component.async_register_entity_service(SERVICE_DECREMENT, {}, "async_decrement")
|
||||
component.async_register_entity_service(SERVICE_RESET, {}, "async_reset")
|
||||
component.async_register_entity_service(
|
||||
SERVICE_INCREMENT, ENTITY_SERVICE_SCHEMA, "async_increment"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_DECREMENT, ENTITY_SERVICE_SCHEMA, "async_decrement"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_RESET, ENTITY_SERVICE_SCHEMA, "async_reset"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CONFIGURE, SERVICE_SCHEMA_CONFIGURE, "async_configure"
|
||||
SERVICE_CONFIGURE,
|
||||
{
|
||||
vol.Optional(ATTR_MINIMUM): vol.Any(None, vol.Coerce(int)),
|
||||
vol.Optional(ATTR_MAXIMUM): vol.Any(None, vol.Coerce(int)),
|
||||
vol.Optional(ATTR_STEP): cv.positive_int,
|
||||
vol.Optional(ATTR_INITIAL): cv.positive_int,
|
||||
vol.Optional(VALUE): cv.positive_int,
|
||||
},
|
||||
"async_configure",
|
||||
)
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
|
|
|
@ -13,7 +13,6 @@ from homeassistant.helpers.config_validation import ( # noqa: F401
|
|||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
)
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.components import group
|
||||
from homeassistant.const import (
|
||||
SERVICE_OPEN_COVER,
|
||||
|
@ -83,18 +82,6 @@ ATTR_POSITION = "position"
|
|||
ATTR_TILT_POSITION = "tilt_position"
|
||||
|
||||
|
||||
COVER_SET_COVER_POSITION_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_POSITION): vol.All(vol.Coerce(int), vol.Range(min=0, max=100))}
|
||||
)
|
||||
|
||||
COVER_SET_COVER_TILT_POSITION_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(ATTR_TILT_POSITION): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=0, max=100)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def is_closed(hass, entity_id=None):
|
||||
|
@ -111,48 +98,50 @@ async def async_setup(hass, config):
|
|||
|
||||
await component.async_setup(config)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_OPEN_COVER, ENTITY_SERVICE_SCHEMA, "async_open_cover"
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_OPEN_COVER, {}, "async_open_cover")
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CLOSE_COVER, ENTITY_SERVICE_SCHEMA, "async_close_cover"
|
||||
SERVICE_CLOSE_COVER, {}, "async_close_cover"
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
COVER_SET_COVER_POSITION_SCHEMA,
|
||||
{
|
||||
vol.Required(ATTR_POSITION): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=0, max=100)
|
||||
)
|
||||
},
|
||||
"async_set_cover_position",
|
||||
)
|
||||
|
||||
component.async_register_entity_service(SERVICE_STOP_COVER, {}, "async_stop_cover")
|
||||
|
||||
component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle")
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_STOP_COVER, ENTITY_SERVICE_SCHEMA, "async_stop_cover"
|
||||
SERVICE_OPEN_COVER_TILT, {}, "async_open_cover_tilt"
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE, ENTITY_SERVICE_SCHEMA, "async_toggle"
|
||||
SERVICE_CLOSE_COVER_TILT, {}, "async_close_cover_tilt"
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_OPEN_COVER_TILT, ENTITY_SERVICE_SCHEMA, "async_open_cover_tilt"
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CLOSE_COVER_TILT, ENTITY_SERVICE_SCHEMA, "async_close_cover_tilt"
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_STOP_COVER_TILT, ENTITY_SERVICE_SCHEMA, "async_stop_cover_tilt"
|
||||
SERVICE_STOP_COVER_TILT, {}, "async_stop_cover_tilt"
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_COVER_TILT_POSITION,
|
||||
COVER_SET_COVER_TILT_POSITION_SCHEMA,
|
||||
{
|
||||
vol.Required(ATTR_TILT_POSITION): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=0, max=100)
|
||||
)
|
||||
},
|
||||
"async_set_cover_tilt_position",
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE_COVER_TILT, ENTITY_SERVICE_SCHEMA, "async_toggle_tilt"
|
||||
SERVICE_TOGGLE_COVER_TILT, {}, "async_toggle_tilt"
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -12,7 +12,6 @@ from homeassistant.loader import bind_hass
|
|||
from homeassistant.helpers.entity import ToggleEntity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
)
|
||||
|
@ -57,20 +56,6 @@ PROP_TO_ATTR = {
|
|||
"current_direction": ATTR_DIRECTION,
|
||||
}
|
||||
|
||||
FAN_SET_SPEED_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_SPEED): cv.string}
|
||||
)
|
||||
|
||||
FAN_TURN_ON_SCHEMA = ENTITY_SERVICE_SCHEMA.extend({vol.Optional(ATTR_SPEED): cv.string})
|
||||
|
||||
FAN_OSCILLATE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_OSCILLATING): cv.boolean}
|
||||
)
|
||||
|
||||
FAN_SET_DIRECTION_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Optional(ATTR_DIRECTION): cv.string}
|
||||
)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def is_on(hass, entity_id: Optional[str] = None) -> bool:
|
||||
|
@ -89,22 +74,22 @@ async def async_setup(hass, config: dict):
|
|||
await component.async_setup(config)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_ON, FAN_TURN_ON_SCHEMA, "async_turn_on"
|
||||
SERVICE_TURN_ON, {vol.Optional(ATTR_SPEED): cv.string}, "async_turn_on"
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off")
|
||||
component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle")
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_SPEED, {vol.Required(ATTR_SPEED): cv.string}, "async_set_speed"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, ENTITY_SERVICE_SCHEMA, "async_turn_off"
|
||||
SERVICE_OSCILLATE,
|
||||
{vol.Required(ATTR_OSCILLATING): cv.boolean},
|
||||
"async_oscillate",
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE, ENTITY_SERVICE_SCHEMA, "async_toggle"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_SPEED, FAN_SET_SPEED_SCHEMA, "async_set_speed"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_OSCILLATE, FAN_OSCILLATE_SCHEMA, "async_oscillate"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_DIRECTION, FAN_SET_DIRECTION_SCHEMA, "async_set_direction"
|
||||
SERVICE_SET_DIRECTION,
|
||||
{vol.Optional(ATTR_DIRECTION): cv.string},
|
||||
"async_set_direction",
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -32,7 +32,7 @@ from homeassistant.helpers.entity import Entity, async_generate_entity_id
|
|||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.event import async_track_state_change
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.config_validation import make_entity_service_schema
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
|
||||
|
@ -63,28 +63,6 @@ SERVICE_REMOVE = "remove"
|
|||
|
||||
CONTROL_TYPES = vol.In(["hidden", None])
|
||||
|
||||
SET_VISIBILITY_SERVICE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_VISIBLE): cv.boolean}
|
||||
)
|
||||
|
||||
RELOAD_SERVICE_SCHEMA = vol.Schema({})
|
||||
|
||||
SET_SERVICE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_OBJECT_ID): cv.slug,
|
||||
vol.Optional(ATTR_NAME): cv.string,
|
||||
vol.Optional(ATTR_VIEW): cv.boolean,
|
||||
vol.Optional(ATTR_ICON): cv.string,
|
||||
vol.Optional(ATTR_CONTROL): CONTROL_TYPES,
|
||||
vol.Optional(ATTR_VISIBLE): cv.boolean,
|
||||
vol.Optional(ATTR_ALL): cv.boolean,
|
||||
vol.Exclusive(ATTR_ENTITIES, "entities"): cv.entity_ids,
|
||||
vol.Exclusive(ATTR_ADD_ENTITIES, "entities"): cv.entity_ids,
|
||||
}
|
||||
)
|
||||
|
||||
REMOVE_SERVICE_SCHEMA = vol.Schema({vol.Required(ATTR_OBJECT_ID): cv.slug})
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -227,7 +205,7 @@ async def async_setup(hass, config):
|
|||
await component.async_add_entities(auto)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=RELOAD_SERVICE_SCHEMA
|
||||
DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=vol.Schema({})
|
||||
)
|
||||
|
||||
service_lock = asyncio.Lock()
|
||||
|
@ -319,11 +297,29 @@ async def async_setup(hass, config):
|
|||
await component.async_remove_entity(entity_id)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SET, locked_service_handler, schema=SET_SERVICE_SCHEMA
|
||||
DOMAIN,
|
||||
SERVICE_SET,
|
||||
locked_service_handler,
|
||||
schema=vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_OBJECT_ID): cv.slug,
|
||||
vol.Optional(ATTR_NAME): cv.string,
|
||||
vol.Optional(ATTR_VIEW): cv.boolean,
|
||||
vol.Optional(ATTR_ICON): cv.string,
|
||||
vol.Optional(ATTR_CONTROL): CONTROL_TYPES,
|
||||
vol.Optional(ATTR_VISIBLE): cv.boolean,
|
||||
vol.Optional(ATTR_ALL): cv.boolean,
|
||||
vol.Exclusive(ATTR_ENTITIES, "entities"): cv.entity_ids,
|
||||
vol.Exclusive(ATTR_ADD_ENTITIES, "entities"): cv.entity_ids,
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_REMOVE, groups_service_handler, schema=REMOVE_SERVICE_SCHEMA
|
||||
DOMAIN,
|
||||
SERVICE_REMOVE,
|
||||
groups_service_handler,
|
||||
schema=vol.Schema({vol.Required(ATTR_OBJECT_ID): cv.slug}),
|
||||
)
|
||||
|
||||
async def visibility_service_handler(service):
|
||||
|
@ -344,7 +340,7 @@ async def async_setup(hass, config):
|
|||
DOMAIN,
|
||||
SERVICE_SET_VISIBILITY,
|
||||
visibility_service_handler,
|
||||
schema=SET_VISIBILITY_SERVICE_SCHEMA,
|
||||
schema=make_entity_service_schema({vol.Required(ATTR_VISIBLE): cv.boolean}),
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -11,7 +11,7 @@ from homeassistant.const import ATTR_ENTITY_ID, ATTR_NAME, CONF_ENTITY_ID, CONF_
|
|||
from homeassistant.core import callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.config_validation import make_entity_service_schema
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.util.async_ import run_callback_threadsafe
|
||||
|
@ -124,7 +124,7 @@ async def async_setup(hass, config):
|
|||
await asyncio.wait(update_tasks)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_SCAN, async_scan_service, schema=ENTITY_SERVICE_SCHEMA
|
||||
DOMAIN, SERVICE_SCAN, async_scan_service, schema=make_entity_service_schema({})
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -13,7 +13,6 @@ from homeassistant.const import (
|
|||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
@ -68,17 +67,11 @@ async def async_setup(hass, config):
|
|||
if not entities:
|
||||
return False
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_ON, ENTITY_SERVICE_SCHEMA, "async_turn_on"
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_turn_on")
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, ENTITY_SERVICE_SCHEMA, "async_turn_off"
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off")
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE, ENTITY_SERVICE_SCHEMA, "async_toggle"
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle")
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
return True
|
||||
|
|
|
@ -6,7 +6,6 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant.const import ATTR_DATE, ATTR_TIME, CONF_ICON, CONF_NAME
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
@ -27,14 +26,6 @@ ATTR_DATETIME = "datetime"
|
|||
|
||||
SERVICE_SET_DATETIME = "set_datetime"
|
||||
|
||||
SERVICE_SET_DATETIME_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional(ATTR_DATE): cv.date,
|
||||
vol.Optional(ATTR_TIME): cv.time,
|
||||
vol.Optional(ATTR_DATETIME): cv.datetime,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def has_date_or_time(conf):
|
||||
"""Check at least date or time is true."""
|
||||
|
@ -108,7 +99,13 @@ async def async_setup(hass, config):
|
|||
entity.async_set_datetime(date, time)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_DATETIME, SERVICE_SET_DATETIME_SCHEMA, async_set_datetime_service
|
||||
SERVICE_SET_DATETIME,
|
||||
{
|
||||
vol.Optional(ATTR_DATE): cv.date,
|
||||
vol.Optional(ATTR_TIME): cv.time,
|
||||
vol.Optional(ATTR_DATETIME): cv.datetime,
|
||||
},
|
||||
async_set_datetime_service,
|
||||
)
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
|
|
|
@ -4,7 +4,6 @@ import logging
|
|||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.const import (
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
ATTR_MODE,
|
||||
|
@ -38,10 +37,6 @@ SERVICE_SET_VALUE = "set_value"
|
|||
SERVICE_INCREMENT = "increment"
|
||||
SERVICE_DECREMENT = "decrement"
|
||||
|
||||
SERVICE_SET_VALUE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_VALUE): vol.Coerce(float)}
|
||||
)
|
||||
|
||||
|
||||
def _cv_input_number(cfg):
|
||||
"""Configure validation helper for input number (voluptuous)."""
|
||||
|
@ -110,16 +105,14 @@ async def async_setup(hass, config):
|
|||
return False
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_VALUE, SERVICE_SET_VALUE_SCHEMA, "async_set_value"
|
||||
SERVICE_SET_VALUE,
|
||||
{vol.Required(ATTR_VALUE): vol.Coerce(float)},
|
||||
"async_set_value",
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_INCREMENT, ENTITY_SERVICE_SCHEMA, "async_increment"
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_INCREMENT, {}, "async_increment")
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_DECREMENT, ENTITY_SERVICE_SCHEMA, "async_decrement"
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_DECREMENT, {}, "async_decrement")
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
return True
|
||||
|
|
|
@ -5,7 +5,6 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant.const import CONF_ICON, CONF_NAME
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
||||
|
@ -22,9 +21,6 @@ ATTR_OPTIONS = "options"
|
|||
|
||||
SERVICE_SELECT_OPTION = "select_option"
|
||||
|
||||
SERVICE_SELECT_OPTION_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_OPTION): cv.string}
|
||||
)
|
||||
|
||||
SERVICE_SELECT_NEXT = "select_next"
|
||||
|
||||
|
@ -32,14 +28,6 @@ SERVICE_SELECT_PREVIOUS = "select_previous"
|
|||
|
||||
SERVICE_SET_OPTIONS = "set_options"
|
||||
|
||||
SERVICE_SET_OPTIONS_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(ATTR_OPTIONS): vol.All(
|
||||
cv.ensure_list, vol.Length(min=1), [cv.string]
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _cv_input_select(cfg):
|
||||
"""Configure validation helper for input select (voluptuous)."""
|
||||
|
@ -92,23 +80,27 @@ async def async_setup(hass, config):
|
|||
return False
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_OPTION, SERVICE_SELECT_OPTION_SCHEMA, "async_select_option"
|
||||
SERVICE_SELECT_OPTION,
|
||||
{vol.Required(ATTR_OPTION): cv.string},
|
||||
"async_select_option",
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_NEXT,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
lambda entity, call: entity.async_offset_index(1),
|
||||
SERVICE_SELECT_NEXT, {}, lambda entity, call: entity.async_offset_index(1),
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_PREVIOUS,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
lambda entity, call: entity.async_offset_index(-1),
|
||||
SERVICE_SELECT_PREVIOUS, {}, lambda entity, call: entity.async_offset_index(-1),
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_OPTIONS, SERVICE_SET_OPTIONS_SCHEMA, "async_set_options"
|
||||
SERVICE_SET_OPTIONS,
|
||||
{
|
||||
vol.Required(ATTR_OPTIONS): vol.All(
|
||||
cv.ensure_list, vol.Length(min=1), [cv.string]
|
||||
)
|
||||
},
|
||||
"async_set_options",
|
||||
)
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
|
|
|
@ -4,7 +4,6 @@ import logging
|
|||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.const import (
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
ATTR_MODE,
|
||||
|
@ -34,10 +33,6 @@ ATTR_PATTERN = "pattern"
|
|||
|
||||
SERVICE_SET_VALUE = "set_value"
|
||||
|
||||
SERVICE_SET_VALUE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_VALUE): cv.string}
|
||||
)
|
||||
|
||||
|
||||
def _cv_input_text(cfg):
|
||||
"""Configure validation helper for input box (voluptuous)."""
|
||||
|
@ -111,7 +106,7 @@ async def async_setup(hass, config):
|
|||
return False
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_VALUE, SERVICE_SET_VALUE_SCHEMA, "async_set_value"
|
||||
SERVICE_SET_VALUE, {vol.Required(ATTR_VALUE): cv.string}, "async_set_value"
|
||||
)
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
|
|
|
@ -66,8 +66,9 @@ ATTR_INFRARED = "infrared"
|
|||
ATTR_ZONES = "zones"
|
||||
ATTR_POWER = "power"
|
||||
|
||||
LIFX_SET_STATE_SCHEMA = LIGHT_TURN_ON_SCHEMA.extend(
|
||||
LIFX_SET_STATE_SCHEMA = cv.make_entity_service_schema(
|
||||
{
|
||||
**LIGHT_TURN_ON_SCHEMA,
|
||||
ATTR_INFRARED: vol.All(vol.Coerce(int), vol.Clamp(min=0, max=255)),
|
||||
ATTR_ZONES: vol.All(cv.ensure_list, [cv.positive_int]),
|
||||
ATTR_POWER: cv.boolean,
|
||||
|
@ -369,16 +370,11 @@ class LIFXManager:
|
|||
async def async_service_to_entities(self, service):
|
||||
"""Return the known entities that a service call mentions."""
|
||||
entity_ids = await async_extract_entity_ids(self.hass, service)
|
||||
if entity_ids:
|
||||
entities = [
|
||||
entity
|
||||
for entity in self.entities.values()
|
||||
if entity.entity_id in entity_ids
|
||||
]
|
||||
else:
|
||||
entities = list(self.entities.values())
|
||||
|
||||
return entities
|
||||
return [
|
||||
entity
|
||||
for entity in self.entities.values()
|
||||
if entity.entity_id in entity_ids
|
||||
]
|
||||
|
||||
@callback
|
||||
def register(self, bulb):
|
||||
|
|
|
@ -22,7 +22,7 @@ import homeassistant.helpers.config_validation as cv
|
|||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
make_entity_service_schema,
|
||||
)
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
|
@ -93,49 +93,37 @@ VALID_TRANSITION = vol.All(vol.Coerce(float), vol.Clamp(min=0, max=6553))
|
|||
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))
|
||||
|
||||
LIGHT_TURN_ON_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Exclusive(ATTR_PROFILE, COLOR_GROUP): cv.string,
|
||||
ATTR_TRANSITION: VALID_TRANSITION,
|
||||
ATTR_BRIGHTNESS: VALID_BRIGHTNESS,
|
||||
ATTR_BRIGHTNESS_PCT: VALID_BRIGHTNESS_PCT,
|
||||
vol.Exclusive(ATTR_COLOR_NAME, COLOR_GROUP): cv.string,
|
||||
vol.Exclusive(ATTR_RGB_COLOR, COLOR_GROUP): vol.All(
|
||||
vol.ExactSequence((cv.byte, cv.byte, cv.byte)), vol.Coerce(tuple)
|
||||
),
|
||||
vol.Exclusive(ATTR_XY_COLOR, COLOR_GROUP): vol.All(
|
||||
vol.ExactSequence((cv.small_float, cv.small_float)), vol.Coerce(tuple)
|
||||
),
|
||||
vol.Exclusive(ATTR_HS_COLOR, COLOR_GROUP): vol.All(
|
||||
vol.ExactSequence(
|
||||
(
|
||||
vol.All(vol.Coerce(float), vol.Range(min=0, max=360)),
|
||||
vol.All(vol.Coerce(float), vol.Range(min=0, max=100)),
|
||||
)
|
||||
),
|
||||
vol.Coerce(tuple),
|
||||
),
|
||||
vol.Exclusive(ATTR_COLOR_TEMP, COLOR_GROUP): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1)
|
||||
),
|
||||
vol.Exclusive(ATTR_KELVIN, COLOR_GROUP): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=0)
|
||||
),
|
||||
ATTR_WHITE_VALUE: vol.All(vol.Coerce(int), vol.Range(min=0, max=255)),
|
||||
ATTR_FLASH: vol.In([FLASH_SHORT, FLASH_LONG]),
|
||||
ATTR_EFFECT: cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
LIGHT_TURN_OFF_SCHEMA = {
|
||||
LIGHT_TURN_ON_SCHEMA = {
|
||||
vol.Exclusive(ATTR_PROFILE, COLOR_GROUP): cv.string,
|
||||
ATTR_TRANSITION: VALID_TRANSITION,
|
||||
ATTR_BRIGHTNESS: VALID_BRIGHTNESS,
|
||||
ATTR_BRIGHTNESS_PCT: VALID_BRIGHTNESS_PCT,
|
||||
vol.Exclusive(ATTR_COLOR_NAME, COLOR_GROUP): cv.string,
|
||||
vol.Exclusive(ATTR_RGB_COLOR, COLOR_GROUP): vol.All(
|
||||
vol.ExactSequence((cv.byte, cv.byte, cv.byte)), vol.Coerce(tuple)
|
||||
),
|
||||
vol.Exclusive(ATTR_XY_COLOR, COLOR_GROUP): vol.All(
|
||||
vol.ExactSequence((cv.small_float, cv.small_float)), vol.Coerce(tuple)
|
||||
),
|
||||
vol.Exclusive(ATTR_HS_COLOR, COLOR_GROUP): vol.All(
|
||||
vol.ExactSequence(
|
||||
(
|
||||
vol.All(vol.Coerce(float), vol.Range(min=0, max=360)),
|
||||
vol.All(vol.Coerce(float), vol.Range(min=0, max=100)),
|
||||
)
|
||||
),
|
||||
vol.Coerce(tuple),
|
||||
),
|
||||
vol.Exclusive(ATTR_COLOR_TEMP, COLOR_GROUP): vol.All(
|
||||
vol.Coerce(int), vol.Range(min=1)
|
||||
),
|
||||
vol.Exclusive(ATTR_KELVIN, COLOR_GROUP): vol.All(vol.Coerce(int), vol.Range(min=0)),
|
||||
ATTR_WHITE_VALUE: vol.All(vol.Coerce(int), vol.Range(min=0, max=255)),
|
||||
ATTR_FLASH: vol.In([FLASH_SHORT, FLASH_LONG]),
|
||||
ATTR_EFFECT: cv.string,
|
||||
}
|
||||
|
||||
|
||||
LIGHT_TOGGLE_SCHEMA = LIGHT_TURN_ON_SCHEMA
|
||||
|
||||
PROFILE_SCHEMA = vol.Schema(
|
||||
vol.ExactSequence((str, cv.small_float, cv.small_float, cv.byte))
|
||||
)
|
||||
|
@ -268,15 +256,20 @@ async def async_setup(hass, config):
|
|||
DOMAIN,
|
||||
SERVICE_TURN_ON,
|
||||
async_handle_light_on_service,
|
||||
schema=LIGHT_TURN_ON_SCHEMA,
|
||||
schema=cv.make_entity_service_schema(LIGHT_TURN_ON_SCHEMA),
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, LIGHT_TURN_OFF_SCHEMA, "async_turn_off"
|
||||
SERVICE_TURN_OFF,
|
||||
{
|
||||
ATTR_TRANSITION: VALID_TRANSITION,
|
||||
ATTR_FLASH: vol.In([FLASH_SHORT, FLASH_LONG]),
|
||||
},
|
||||
"async_turn_off",
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE, LIGHT_TOGGLE_SCHEMA, "async_toggle"
|
||||
SERVICE_TOGGLE, LIGHT_TURN_ON_SCHEMA, "async_toggle"
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -9,7 +9,7 @@ from homeassistant.loader import bind_hass
|
|||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
make_entity_service_schema,
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
)
|
||||
|
@ -40,7 +40,7 @@ GROUP_NAME_ALL_LOCKS = "all locks"
|
|||
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||
|
||||
LOCK_SERVICE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend({vol.Optional(ATTR_CODE): cv.string})
|
||||
LOCK_SERVICE_SCHEMA = make_entity_service_schema({vol.Optional(ATTR_CODE): cv.string})
|
||||
|
||||
# Bitfield of features supported by the lock entity
|
||||
SUPPORT_OPEN = 1
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
from youtube_dl import YoutubeDL
|
||||
from youtube_dl.utils import DownloadError, ExtractorError
|
||||
|
||||
from homeassistant.components.media_player import MEDIA_PLAYER_PLAY_MEDIA_SCHEMA
|
||||
from homeassistant.components.media_player.const import (
|
||||
|
@ -44,7 +46,10 @@ def setup(hass, config):
|
|||
MediaExtractor(hass, config[DOMAIN], call.data).extract_and_send()
|
||||
|
||||
hass.services.register(
|
||||
DOMAIN, SERVICE_PLAY_MEDIA, play_media, schema=MEDIA_PLAYER_PLAY_MEDIA_SCHEMA
|
||||
DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
play_media,
|
||||
schema=cv.make_entity_service_schema(MEDIA_PLAYER_PLAY_MEDIA_SCHEMA),
|
||||
)
|
||||
|
||||
return True
|
||||
|
@ -98,9 +103,6 @@ class MediaExtractor:
|
|||
|
||||
def get_stream_selector(self):
|
||||
"""Return format selector for the media URL."""
|
||||
from youtube_dl import YoutubeDL
|
||||
from youtube_dl.utils import DownloadError, ExtractorError
|
||||
|
||||
ydl = YoutubeDL({"quiet": True, "logger": _LOGGER})
|
||||
|
||||
try:
|
||||
|
|
|
@ -40,7 +40,6 @@ from homeassistant.const import (
|
|||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
)
|
||||
|
@ -123,42 +122,12 @@ DEVICE_CLASSES = [DEVICE_CLASS_TV, DEVICE_CLASS_SPEAKER]
|
|||
|
||||
DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(DEVICE_CLASSES))
|
||||
|
||||
# Service call validation schemas
|
||||
MEDIA_PLAYER_SET_VOLUME_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_MEDIA_VOLUME_LEVEL): cv.small_float}
|
||||
)
|
||||
|
||||
MEDIA_PLAYER_MUTE_VOLUME_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_MEDIA_VOLUME_MUTED): cv.boolean}
|
||||
)
|
||||
|
||||
MEDIA_PLAYER_MEDIA_SEEK_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(ATTR_MEDIA_SEEK_POSITION): vol.All(
|
||||
vol.Coerce(float), vol.Range(min=0)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
MEDIA_PLAYER_SELECT_SOURCE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_INPUT_SOURCE): cv.string}
|
||||
)
|
||||
|
||||
MEDIA_PLAYER_SELECT_SOUND_MODE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_SOUND_MODE): cv.string}
|
||||
)
|
||||
|
||||
MEDIA_PLAYER_PLAY_MEDIA_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(ATTR_MEDIA_CONTENT_TYPE): cv.string,
|
||||
vol.Required(ATTR_MEDIA_CONTENT_ID): cv.string,
|
||||
vol.Optional(ATTR_MEDIA_ENQUEUE): cv.boolean,
|
||||
}
|
||||
)
|
||||
|
||||
MEDIA_PLAYER_SET_SHUFFLE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_MEDIA_SHUFFLE): cv.boolean}
|
||||
)
|
||||
MEDIA_PLAYER_PLAY_MEDIA_SCHEMA = {
|
||||
vol.Required(ATTR_MEDIA_CONTENT_TYPE): cv.string,
|
||||
vol.Required(ATTR_MEDIA_CONTENT_ID): cv.string,
|
||||
vol.Optional(ATTR_MEDIA_ENQUEUE): cv.boolean,
|
||||
}
|
||||
|
||||
ATTR_TO_PROPERTY = [
|
||||
ATTR_MEDIA_VOLUME_LEVEL,
|
||||
|
@ -223,65 +192,56 @@ async def async_setup(hass, config):
|
|||
await component.async_setup(config)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_ON, ENTITY_SERVICE_SCHEMA, "async_turn_on", [SUPPORT_TURN_ON]
|
||||
SERVICE_TURN_ON, {}, "async_turn_on", [SUPPORT_TURN_ON]
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, ENTITY_SERVICE_SCHEMA, "async_turn_off", [SUPPORT_TURN_OFF]
|
||||
SERVICE_TURN_OFF, {}, "async_turn_off", [SUPPORT_TURN_OFF]
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
"async_toggle",
|
||||
[SUPPORT_TURN_OFF | SUPPORT_TURN_ON],
|
||||
SERVICE_TOGGLE, {}, "async_toggle", [SUPPORT_TURN_OFF | SUPPORT_TURN_ON],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_VOLUME_UP,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
{},
|
||||
"async_volume_up",
|
||||
[SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_VOLUME_DOWN,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
{},
|
||||
"async_volume_down",
|
||||
[SUPPORT_VOLUME_SET, SUPPORT_VOLUME_STEP],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_MEDIA_PLAY_PAUSE,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
{},
|
||||
"async_media_play_pause",
|
||||
[SUPPORT_PLAY | SUPPORT_PAUSE],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_MEDIA_PLAY, ENTITY_SERVICE_SCHEMA, "async_media_play", [SUPPORT_PLAY]
|
||||
SERVICE_MEDIA_PLAY, {}, "async_media_play", [SUPPORT_PLAY]
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_MEDIA_PAUSE, ENTITY_SERVICE_SCHEMA, "async_media_pause", [SUPPORT_PAUSE]
|
||||
SERVICE_MEDIA_PAUSE, {}, "async_media_pause", [SUPPORT_PAUSE]
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_MEDIA_STOP, ENTITY_SERVICE_SCHEMA, "async_media_stop", [SUPPORT_STOP]
|
||||
SERVICE_MEDIA_STOP, {}, "async_media_stop", [SUPPORT_STOP]
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_MEDIA_NEXT_TRACK,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
"async_media_next_track",
|
||||
[SUPPORT_NEXT_TRACK],
|
||||
SERVICE_MEDIA_NEXT_TRACK, {}, "async_media_next_track", [SUPPORT_NEXT_TRACK],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_MEDIA_PREVIOUS_TRACK,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
{},
|
||||
"async_media_previous_track",
|
||||
[SUPPORT_PREVIOUS_TRACK],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CLEAR_PLAYLIST,
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
"async_clear_playlist",
|
||||
[SUPPORT_CLEAR_PLAYLIST],
|
||||
SERVICE_CLEAR_PLAYLIST, {}, "async_clear_playlist", [SUPPORT_CLEAR_PLAYLIST],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_VOLUME_SET,
|
||||
MEDIA_PLAYER_SET_VOLUME_SCHEMA,
|
||||
{vol.Required(ATTR_MEDIA_VOLUME_LEVEL): cv.small_float},
|
||||
lambda entity, call: entity.async_set_volume_level(
|
||||
volume=call.data[ATTR_MEDIA_VOLUME_LEVEL]
|
||||
),
|
||||
|
@ -289,7 +249,7 @@ async def async_setup(hass, config):
|
|||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_VOLUME_MUTE,
|
||||
MEDIA_PLAYER_MUTE_VOLUME_SCHEMA,
|
||||
{vol.Required(ATTR_MEDIA_VOLUME_MUTED): cv.boolean},
|
||||
lambda entity, call: entity.async_mute_volume(
|
||||
mute=call.data[ATTR_MEDIA_VOLUME_MUTED]
|
||||
),
|
||||
|
@ -297,7 +257,11 @@ async def async_setup(hass, config):
|
|||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_MEDIA_SEEK,
|
||||
MEDIA_PLAYER_MEDIA_SEEK_SCHEMA,
|
||||
{
|
||||
vol.Required(ATTR_MEDIA_SEEK_POSITION): vol.All(
|
||||
vol.Coerce(float), vol.Range(min=0)
|
||||
)
|
||||
},
|
||||
lambda entity, call: entity.async_media_seek(
|
||||
position=call.data[ATTR_MEDIA_SEEK_POSITION]
|
||||
),
|
||||
|
@ -305,13 +269,13 @@ async def async_setup(hass, config):
|
|||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_SOURCE,
|
||||
MEDIA_PLAYER_SELECT_SOURCE_SCHEMA,
|
||||
{vol.Required(ATTR_INPUT_SOURCE): cv.string},
|
||||
"async_select_source",
|
||||
[SUPPORT_SELECT_SOURCE],
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_SOUND_MODE,
|
||||
MEDIA_PLAYER_SELECT_SOUND_MODE_SCHEMA,
|
||||
{vol.Required(ATTR_SOUND_MODE): cv.string},
|
||||
"async_select_sound_mode",
|
||||
[SUPPORT_SELECT_SOUND_MODE],
|
||||
)
|
||||
|
@ -327,7 +291,7 @@ async def async_setup(hass, config):
|
|||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SHUFFLE_SET,
|
||||
MEDIA_PLAYER_SET_SHUFFLE_SCHEMA,
|
||||
{vol.Required(ATTR_MEDIA_SHUFFLE): cv.boolean},
|
||||
"async_set_shuffle",
|
||||
[SUPPORT_SHUFFLE_SET],
|
||||
)
|
||||
|
|
|
@ -17,7 +17,7 @@ from homeassistant.const import (
|
|||
)
|
||||
from homeassistant.components import group
|
||||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
make_entity_service_schema,
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
)
|
||||
|
@ -56,29 +56,10 @@ DEFAULT_HOLD_SECS = 0
|
|||
|
||||
SUPPORT_LEARN_COMMAND = 1
|
||||
|
||||
REMOTE_SERVICE_ACTIVITY_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
REMOTE_SERVICE_ACTIVITY_SCHEMA = make_entity_service_schema(
|
||||
{vol.Optional(ATTR_ACTIVITY): cv.string}
|
||||
)
|
||||
|
||||
REMOTE_SERVICE_SEND_COMMAND_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(ATTR_COMMAND): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(ATTR_DEVICE): cv.string,
|
||||
vol.Optional(ATTR_NUM_REPEATS, default=DEFAULT_NUM_REPEATS): cv.positive_int,
|
||||
vol.Optional(ATTR_DELAY_SECS): vol.Coerce(float),
|
||||
vol.Optional(ATTR_HOLD_SECS, default=DEFAULT_HOLD_SECS): vol.Coerce(float),
|
||||
}
|
||||
)
|
||||
|
||||
REMOTE_SERVICE_LEARN_COMMAND_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Optional(ATTR_DEVICE): cv.string,
|
||||
vol.Optional(ATTR_COMMAND): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(ATTR_ALTERNATIVE): cv.boolean,
|
||||
vol.Optional(ATTR_TIMEOUT): cv.positive_int,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def is_on(hass, entity_id=None):
|
||||
|
@ -107,12 +88,27 @@ async def async_setup(hass, config):
|
|||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SEND_COMMAND, REMOTE_SERVICE_SEND_COMMAND_SCHEMA, "async_send_command"
|
||||
SERVICE_SEND_COMMAND,
|
||||
{
|
||||
vol.Required(ATTR_COMMAND): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(ATTR_DEVICE): cv.string,
|
||||
vol.Optional(
|
||||
ATTR_NUM_REPEATS, default=DEFAULT_NUM_REPEATS
|
||||
): cv.positive_int,
|
||||
vol.Optional(ATTR_DELAY_SECS): vol.Coerce(float),
|
||||
vol.Optional(ATTR_HOLD_SECS, default=DEFAULT_HOLD_SECS): vol.Coerce(float),
|
||||
},
|
||||
"async_send_command",
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_LEARN_COMMAND,
|
||||
REMOTE_SERVICE_LEARN_COMMAND_SCHEMA,
|
||||
{
|
||||
vol.Optional(ATTR_DEVICE): cv.string,
|
||||
vol.Optional(ATTR_COMMAND): vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(ATTR_ALTERNATIVE): cv.boolean,
|
||||
vol.Optional(ATTR_TIMEOUT): cv.positive_int,
|
||||
},
|
||||
"async_learn_command",
|
||||
)
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ from homeassistant.loader import bind_hass
|
|||
from homeassistant.helpers.entity import ToggleEntity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.config_validation import make_entity_service_schema
|
||||
from homeassistant.helpers.service import async_set_service_schema
|
||||
|
||||
from homeassistant.helpers.script import Script
|
||||
|
@ -60,7 +60,7 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
)
|
||||
|
||||
SCRIPT_SERVICE_SCHEMA = vol.Schema(dict)
|
||||
SCRIPT_TURN_ONOFF_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
SCRIPT_TURN_ONOFF_SCHEMA = make_entity_service_schema(
|
||||
{vol.Optional(ATTR_VARIABLES): dict}
|
||||
)
|
||||
RELOAD_SERVICE_SCHEMA = vol.Schema({})
|
||||
|
|
|
@ -6,7 +6,6 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant.const import CONF_ICON, CONF_NAME
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.event import async_track_point_in_utc_time
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
@ -37,10 +36,6 @@ SERVICE_PAUSE = "pause"
|
|||
SERVICE_CANCEL = "cancel"
|
||||
SERVICE_FINISH = "finish"
|
||||
|
||||
SERVICE_SCHEMA_DURATION = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Optional(ATTR_DURATION, default=timedelta(DEFAULT_DURATION)): cv.time_period}
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: cv.schema_with_slug_keys(
|
||||
|
@ -80,17 +75,17 @@ async def async_setup(hass, config):
|
|||
return False
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_START, SERVICE_SCHEMA_DURATION, "async_start"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_PAUSE, ENTITY_SERVICE_SCHEMA, "async_pause"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CANCEL, ENTITY_SERVICE_SCHEMA, "async_cancel"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_FINISH, ENTITY_SERVICE_SCHEMA, "async_finish"
|
||||
SERVICE_START,
|
||||
{
|
||||
vol.Optional(
|
||||
ATTR_DURATION, default=timedelta(DEFAULT_DURATION)
|
||||
): cv.time_period
|
||||
},
|
||||
"async_start",
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_PAUSE, {}, "async_pause")
|
||||
component.async_register_entity_service(SERVICE_CANCEL, {}, "async_cancel")
|
||||
component.async_register_entity_service(SERVICE_FINISH, {}, "async_finish")
|
||||
|
||||
await component.async_add_entities(entities)
|
||||
return True
|
||||
|
|
|
@ -7,7 +7,6 @@ import voluptuous as vol
|
|||
from homeassistant.const import CONF_NAME
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers import discovery
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.restore_state import RestoreEntity
|
||||
|
@ -39,11 +38,8 @@ ATTR_TARIFFS = "tariffs"
|
|||
|
||||
DEFAULT_OFFSET = timedelta(hours=0)
|
||||
|
||||
SERVICE_SELECT_TARIFF_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_TARIFF): cv.string}
|
||||
)
|
||||
|
||||
METER_CONFIG_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
METER_CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_SOURCE_SENSOR): cv.entity_id,
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
|
@ -110,16 +106,16 @@ async def async_setup(hass, config):
|
|||
register_services = True
|
||||
|
||||
if register_services:
|
||||
component.async_register_entity_service(SERVICE_RESET, {}, "async_reset_meters")
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_RESET, ENTITY_SERVICE_SCHEMA, "async_reset_meters"
|
||||
SERVICE_SELECT_TARIFF,
|
||||
{vol.Required(ATTR_TARIFF): cv.string},
|
||||
"async_select_tariff",
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_TARIFF, SERVICE_SELECT_TARIFF_SCHEMA, "async_select_tariff"
|
||||
)
|
||||
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SELECT_NEXT_TARIFF, ENTITY_SERVICE_SCHEMA, "async_next_tariff"
|
||||
SERVICE_SELECT_NEXT_TARIFF, {}, "async_next_tariff"
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -19,7 +19,7 @@ from homeassistant.const import ( # noqa: F401 # STATE_PAUSED/IDLE are API
|
|||
from homeassistant.loader import bind_hass
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
ENTITY_SERVICE_SCHEMA,
|
||||
make_entity_service_schema,
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
)
|
||||
|
@ -55,16 +55,6 @@ SERVICE_START = "start"
|
|||
SERVICE_PAUSE = "pause"
|
||||
SERVICE_STOP = "stop"
|
||||
|
||||
VACUUM_SET_FAN_SPEED_SERVICE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{vol.Required(ATTR_FAN_SPEED): cv.string}
|
||||
)
|
||||
|
||||
VACUUM_SEND_COMMAND_SERVICE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(ATTR_COMMAND): cv.string,
|
||||
vol.Optional(ATTR_PARAMS): vol.Any(dict, cv.ensure_list),
|
||||
}
|
||||
)
|
||||
|
||||
STATE_CLEANING = "cleaning"
|
||||
STATE_DOCKED = "docked"
|
||||
|
@ -106,43 +96,32 @@ async def async_setup(hass, config):
|
|||
|
||||
await component.async_setup(config)
|
||||
|
||||
component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_turn_on")
|
||||
component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off")
|
||||
component.async_register_entity_service(SERVICE_TOGGLE, {}, "async_toggle")
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_ON, ENTITY_SERVICE_SCHEMA, "async_turn_on"
|
||||
SERVICE_START_PAUSE, {}, "async_start_pause"
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_START, {}, "async_start")
|
||||
component.async_register_entity_service(SERVICE_PAUSE, {}, "async_pause")
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TURN_OFF, ENTITY_SERVICE_SCHEMA, "async_turn_off"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_TOGGLE, ENTITY_SERVICE_SCHEMA, "async_toggle"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_START_PAUSE, ENTITY_SERVICE_SCHEMA, "async_start_pause"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_START, ENTITY_SERVICE_SCHEMA, "async_start"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_PAUSE, ENTITY_SERVICE_SCHEMA, "async_pause"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_RETURN_TO_BASE, ENTITY_SERVICE_SCHEMA, "async_return_to_base"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_CLEAN_SPOT, ENTITY_SERVICE_SCHEMA, "async_clean_spot"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_LOCATE, ENTITY_SERVICE_SCHEMA, "async_locate"
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_STOP, ENTITY_SERVICE_SCHEMA, "async_stop"
|
||||
SERVICE_RETURN_TO_BASE, {}, "async_return_to_base"
|
||||
)
|
||||
component.async_register_entity_service(SERVICE_CLEAN_SPOT, {}, "async_clean_spot")
|
||||
component.async_register_entity_service(SERVICE_LOCATE, {}, "async_locate")
|
||||
component.async_register_entity_service(SERVICE_STOP, {}, "async_stop")
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SET_FAN_SPEED,
|
||||
VACUUM_SET_FAN_SPEED_SERVICE_SCHEMA,
|
||||
{vol.Required(ATTR_FAN_SPEED): cv.string},
|
||||
"async_set_fan_speed",
|
||||
)
|
||||
component.async_register_entity_service(
|
||||
SERVICE_SEND_COMMAND, VACUUM_SEND_COMMAND_SERVICE_SCHEMA, "async_send_command"
|
||||
SERVICE_SEND_COMMAND,
|
||||
{
|
||||
vol.Required(ATTR_COMMAND): cv.string,
|
||||
vol.Optional(ATTR_PARAMS): vol.Any(dict, cv.ensure_list),
|
||||
},
|
||||
"async_send_command",
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -25,7 +25,7 @@ from homeassistant.const import (
|
|||
from homeassistant.core import callback
|
||||
from homeassistant.helpers import discovery
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.config_validation import make_entity_service_schema
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.event import track_time_interval
|
||||
|
@ -131,11 +131,11 @@ CONFIG_SCHEMA = vol.Schema(
|
|||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
RENAME_DEVICE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
RENAME_DEVICE_SCHEMA = make_entity_service_schema(
|
||||
{vol.Required(ATTR_NAME): cv.string}, extra=vol.ALLOW_EXTRA
|
||||
)
|
||||
|
||||
DELETE_DEVICE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA)
|
||||
DELETE_DEVICE_SCHEMA = make_entity_service_schema({}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
SET_PAIRING_MODE_SCHEMA = vol.Schema(
|
||||
{
|
||||
|
@ -146,31 +146,31 @@ SET_PAIRING_MODE_SCHEMA = vol.Schema(
|
|||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
SET_VOLUME_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
SET_VOLUME_SCHEMA = make_entity_service_schema(
|
||||
{vol.Required(ATTR_VOLUME): vol.In(VOLUMES)}
|
||||
)
|
||||
|
||||
SET_SIREN_TONE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
SET_SIREN_TONE_SCHEMA = make_entity_service_schema(
|
||||
{vol.Required(ATTR_TONE): vol.In(TONES)}
|
||||
)
|
||||
|
||||
SET_CHIME_MODE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
SET_CHIME_MODE_SCHEMA = make_entity_service_schema(
|
||||
{vol.Required(ATTR_TONE): vol.In(CHIME_TONES)}
|
||||
)
|
||||
|
||||
SET_AUTO_SHUTOFF_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
SET_AUTO_SHUTOFF_SCHEMA = make_entity_service_schema(
|
||||
{vol.Required(ATTR_AUTO_SHUTOFF): vol.In(AUTO_SHUTOFF_TIMES)}
|
||||
)
|
||||
|
||||
SET_STROBE_ENABLED_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
SET_STROBE_ENABLED_SCHEMA = make_entity_service_schema(
|
||||
{vol.Required(ATTR_ENABLED): cv.boolean}
|
||||
)
|
||||
|
||||
ENABLED_SIREN_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
ENABLED_SIREN_SCHEMA = make_entity_service_schema(
|
||||
{vol.Required(ATTR_ENABLED): cv.boolean}
|
||||
)
|
||||
|
||||
DIAL_CONFIG_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
DIAL_CONFIG_SCHEMA = make_entity_service_schema(
|
||||
{
|
||||
vol.Optional(ATTR_MIN_VALUE): vol.Coerce(int),
|
||||
vol.Optional(ATTR_MAX_VALUE): vol.Coerce(int),
|
||||
|
@ -182,7 +182,7 @@ DIAL_CONFIG_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
|||
}
|
||||
)
|
||||
|
||||
DIAL_STATE_SCHEMA = ENTITY_SERVICE_SCHEMA.extend(
|
||||
DIAL_STATE_SCHEMA = make_entity_service_schema(
|
||||
{
|
||||
vol.Required(ATTR_VALUE): vol.Coerce(int),
|
||||
vol.Optional(ATTR_LABELS): cv.ensure_list(cv.string),
|
||||
|
|
|
@ -715,12 +715,23 @@ PLATFORM_SCHEMA = vol.Schema(
|
|||
|
||||
PLATFORM_SCHEMA_BASE = PLATFORM_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
ENTITY_SERVICE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(ATTR_ENTITY_ID): comp_entity_ids,
|
||||
vol.Optional(ATTR_AREA_ID): vol.All(ensure_list, [str]),
|
||||
}
|
||||
)
|
||||
|
||||
def make_entity_service_schema(
|
||||
schema: dict, *, extra: int = vol.PREVENT_EXTRA
|
||||
) -> vol.All:
|
||||
"""Create an entity service schema."""
|
||||
return vol.All(
|
||||
vol.Schema(
|
||||
{
|
||||
**schema,
|
||||
vol.Optional(ATTR_ENTITY_ID): comp_entity_ids,
|
||||
vol.Optional(ATTR_AREA_ID): vol.All(ensure_list, [str]),
|
||||
},
|
||||
extra=extra,
|
||||
),
|
||||
has_at_least_one_key(ATTR_ENTITY_ID, ATTR_AREA_ID),
|
||||
)
|
||||
|
||||
|
||||
EVENT_SCHEMA = vol.Schema(
|
||||
{
|
||||
|
|
|
@ -15,7 +15,7 @@ from homeassistant.const import (
|
|||
from homeassistant.core import callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import config_per_platform, discovery
|
||||
from homeassistant.helpers.config_validation import ENTITY_SERVICE_SCHEMA
|
||||
from homeassistant.helpers.config_validation import make_entity_service_schema
|
||||
from homeassistant.helpers.service import async_extract_entity_ids
|
||||
from homeassistant.loader import bind_hass, async_get_integration
|
||||
from homeassistant.util import slugify
|
||||
|
@ -173,24 +173,16 @@ class EntityComponent:
|
|||
async def async_extract_from_service(self, service, expand_group=True):
|
||||
"""Extract all known and available entities from a service call.
|
||||
|
||||
Will return all entities if no entities specified in call.
|
||||
Will return an empty list if entities specified but unknown.
|
||||
|
||||
This method must be run in the event loop.
|
||||
"""
|
||||
data_ent_id = service.data.get(ATTR_ENTITY_ID)
|
||||
|
||||
if data_ent_id in (None, ENTITY_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: %s",
|
||||
service.domain,
|
||||
service.service,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
if data_ent_id is None:
|
||||
return []
|
||||
|
||||
if data_ent_id == ENTITY_MATCH_ALL:
|
||||
return [entity for entity in self.entities if entity.available]
|
||||
|
||||
entity_ids = await async_extract_entity_ids(self.hass, service, expand_group)
|
||||
|
@ -204,7 +196,7 @@ class EntityComponent:
|
|||
def async_register_entity_service(self, name, schema, func, required_features=None):
|
||||
"""Register an entity service."""
|
||||
if isinstance(schema, dict):
|
||||
schema = ENTITY_SERVICE_SCHEMA.extend(schema)
|
||||
schema = make_entity_service_schema(schema)
|
||||
|
||||
async def handle_service(call):
|
||||
"""Handle the service."""
|
||||
|
|
|
@ -260,19 +260,7 @@ async def entity_service_call(
|
|||
else:
|
||||
entity_perms = None
|
||||
|
||||
# Are we trying to target all entities
|
||||
if ATTR_ENTITY_ID in call.data:
|
||||
target_all_entities = call.data[ATTR_ENTITY_ID] == ENTITY_MATCH_ALL
|
||||
else:
|
||||
# Remove the service_name parameter along with this warning
|
||||
_LOGGER.warning(
|
||||
"Not passing an entity ID to a service to target all "
|
||||
"entities is deprecated. Update your call to %s to be "
|
||||
"instead: entity_id: %s",
|
||||
service_name,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
target_all_entities = True
|
||||
target_all_entities = call.data.get(ATTR_ENTITY_ID) == ENTITY_MATCH_ALL
|
||||
|
||||
if not target_all_entities:
|
||||
# A set of entities we're trying to target.
|
||||
|
|
|
@ -13,11 +13,12 @@ from homeassistant.const import (
|
|||
SERVICE_ALARM_ARM_AWAY,
|
||||
SERVICE_ALARM_ARM_NIGHT,
|
||||
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
async def async_alarm_disarm(hass, code=None, entity_id=None):
|
||||
async def async_alarm_disarm(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for disarm."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -29,7 +30,7 @@ async def async_alarm_disarm(hass, code=None, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def alarm_disarm(hass, code=None, entity_id=None):
|
||||
def alarm_disarm(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for disarm."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -40,7 +41,7 @@ def alarm_disarm(hass, code=None, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_ALARM_DISARM, data)
|
||||
|
||||
|
||||
async def async_alarm_arm_home(hass, code=None, entity_id=None):
|
||||
async def async_alarm_arm_home(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for disarm."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -52,7 +53,7 @@ async def async_alarm_arm_home(hass, code=None, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def alarm_arm_home(hass, code=None, entity_id=None):
|
||||
def alarm_arm_home(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for arm home."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -63,7 +64,7 @@ def alarm_arm_home(hass, code=None, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_ALARM_ARM_HOME, data)
|
||||
|
||||
|
||||
async def async_alarm_arm_away(hass, code=None, entity_id=None):
|
||||
async def async_alarm_arm_away(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for disarm."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -75,7 +76,7 @@ async def async_alarm_arm_away(hass, code=None, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def alarm_arm_away(hass, code=None, entity_id=None):
|
||||
def alarm_arm_away(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for arm away."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -86,7 +87,7 @@ def alarm_arm_away(hass, code=None, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_ALARM_ARM_AWAY, data)
|
||||
|
||||
|
||||
async def async_alarm_arm_night(hass, code=None, entity_id=None):
|
||||
async def async_alarm_arm_night(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for disarm."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -98,7 +99,7 @@ async def async_alarm_arm_night(hass, code=None, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def alarm_arm_night(hass, code=None, entity_id=None):
|
||||
def alarm_arm_night(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for arm night."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -109,7 +110,7 @@ def alarm_arm_night(hass, code=None, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_ALARM_ARM_NIGHT, data)
|
||||
|
||||
|
||||
async def async_alarm_trigger(hass, code=None, entity_id=None):
|
||||
async def async_alarm_trigger(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for disarm."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -121,7 +122,7 @@ async def async_alarm_trigger(hass, code=None, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def alarm_trigger(hass, code=None, entity_id=None):
|
||||
def alarm_trigger(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for trigger."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -132,7 +133,7 @@ def alarm_trigger(hass, code=None, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_ALARM_TRIGGER, data)
|
||||
|
||||
|
||||
async def async_alarm_arm_custom_bypass(hass, code=None, entity_id=None):
|
||||
async def async_alarm_arm_custom_bypass(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for disarm."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -146,7 +147,7 @@ async def async_alarm_arm_custom_bypass(hass, code=None, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def alarm_arm_custom_bypass(hass, code=None, entity_id=None):
|
||||
def alarm_arm_custom_bypass(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for arm custom bypass."""
|
||||
data = {}
|
||||
if code:
|
||||
|
|
|
@ -10,33 +10,34 @@ from homeassistant.const import (
|
|||
SERVICE_TURN_OFF,
|
||||
SERVICE_TOGGLE,
|
||||
SERVICE_RELOAD,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
async def async_turn_on(hass, entity_id=None):
|
||||
async def async_turn_on(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn on specified automation or all."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
async def async_turn_off(hass, entity_id=None):
|
||||
async def async_turn_off(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn off specified automation or all."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TURN_OFF, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
async def async_toggle(hass, entity_id=None):
|
||||
async def async_toggle(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Toggle specified automation or all."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TOGGLE, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
async def async_trigger(hass, entity_id=None):
|
||||
async def async_trigger(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Trigger specified automation or all."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TRIGGER, data)
|
||||
|
|
|
@ -13,20 +13,25 @@ from homeassistant.components.camera.const import (
|
|||
DATA_CAMERA_PREFS,
|
||||
PREF_PRELOAD_STREAM,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
async def async_turn_off(hass, entity_id=None):
|
||||
async def async_turn_off(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn off camera."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TURN_OFF, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
async def async_turn_on(hass, entity_id=None):
|
||||
async def async_turn_on(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn on camera, and set operation mode."""
|
||||
data = {}
|
||||
if entity_id is not None:
|
||||
|
@ -36,7 +41,7 @@ async def async_turn_on(hass, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def enable_motion_detection(hass, entity_id=None):
|
||||
def enable_motion_detection(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Enable Motion Detection."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_ENABLE_MOTION, data))
|
||||
|
@ -44,7 +49,7 @@ def enable_motion_detection(hass, entity_id=None):
|
|||
|
||||
@bind_hass
|
||||
@callback
|
||||
def async_snapshot(hass, filename, entity_id=None):
|
||||
def async_snapshot(hass, filename, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Make a snapshot from a camera."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
data[ATTR_FILENAME] = filename
|
||||
|
|
|
@ -27,11 +27,12 @@ from homeassistant.const import (
|
|||
ATTR_TEMPERATURE,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
async def async_set_preset_mode(hass, preset_mode, entity_id=None):
|
||||
async def async_set_preset_mode(hass, preset_mode, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set new preset mode."""
|
||||
data = {ATTR_PRESET_MODE: preset_mode}
|
||||
|
||||
|
@ -42,7 +43,7 @@ async def async_set_preset_mode(hass, preset_mode, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def set_preset_mode(hass, preset_mode, entity_id=None):
|
||||
def set_preset_mode(hass, preset_mode, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set new preset mode."""
|
||||
data = {ATTR_PRESET_MODE: preset_mode}
|
||||
|
||||
|
@ -52,7 +53,7 @@ def set_preset_mode(hass, preset_mode, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_SET_PRESET_MODE, data)
|
||||
|
||||
|
||||
async def async_set_aux_heat(hass, aux_heat, entity_id=None):
|
||||
async def async_set_aux_heat(hass, aux_heat, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified climate devices auxiliary heater on."""
|
||||
data = {ATTR_AUX_HEAT: aux_heat}
|
||||
|
||||
|
@ -63,7 +64,7 @@ async def async_set_aux_heat(hass, aux_heat, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def set_aux_heat(hass, aux_heat, entity_id=None):
|
||||
def set_aux_heat(hass, aux_heat, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified climate devices auxiliary heater on."""
|
||||
data = {ATTR_AUX_HEAT: aux_heat}
|
||||
|
||||
|
@ -76,7 +77,7 @@ def set_aux_heat(hass, aux_heat, entity_id=None):
|
|||
async def async_set_temperature(
|
||||
hass,
|
||||
temperature=None,
|
||||
entity_id=None,
|
||||
entity_id=ENTITY_MATCH_ALL,
|
||||
target_temp_high=None,
|
||||
target_temp_low=None,
|
||||
hvac_mode=None,
|
||||
|
@ -103,7 +104,7 @@ async def async_set_temperature(
|
|||
def set_temperature(
|
||||
hass,
|
||||
temperature=None,
|
||||
entity_id=None,
|
||||
entity_id=ENTITY_MATCH_ALL,
|
||||
target_temp_high=None,
|
||||
target_temp_low=None,
|
||||
hvac_mode=None,
|
||||
|
@ -124,7 +125,7 @@ def set_temperature(
|
|||
hass.services.call(DOMAIN, SERVICE_SET_TEMPERATURE, kwargs)
|
||||
|
||||
|
||||
async def async_set_humidity(hass, humidity, entity_id=None):
|
||||
async def async_set_humidity(hass, humidity, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set new target humidity."""
|
||||
data = {ATTR_HUMIDITY: humidity}
|
||||
|
||||
|
@ -135,7 +136,7 @@ async def async_set_humidity(hass, humidity, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def set_humidity(hass, humidity, entity_id=None):
|
||||
def set_humidity(hass, humidity, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set new target humidity."""
|
||||
data = {ATTR_HUMIDITY: humidity}
|
||||
|
||||
|
@ -145,7 +146,7 @@ def set_humidity(hass, humidity, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_SET_HUMIDITY, data)
|
||||
|
||||
|
||||
async def async_set_fan_mode(hass, fan, entity_id=None):
|
||||
async def async_set_fan_mode(hass, fan, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set all or specified climate devices fan mode on."""
|
||||
data = {ATTR_FAN_MODE: fan}
|
||||
|
||||
|
@ -156,7 +157,7 @@ async def async_set_fan_mode(hass, fan, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def set_fan_mode(hass, fan, entity_id=None):
|
||||
def set_fan_mode(hass, fan, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set all or specified climate devices fan mode on."""
|
||||
data = {ATTR_FAN_MODE: fan}
|
||||
|
||||
|
@ -166,7 +167,7 @@ def set_fan_mode(hass, fan, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_SET_FAN_MODE, data)
|
||||
|
||||
|
||||
async def async_set_hvac_mode(hass, hvac_mode, entity_id=None):
|
||||
async def async_set_hvac_mode(hass, hvac_mode, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set new target operation mode."""
|
||||
data = {ATTR_HVAC_MODE: hvac_mode}
|
||||
|
||||
|
@ -177,7 +178,7 @@ async def async_set_hvac_mode(hass, hvac_mode, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def set_operation_mode(hass, hvac_mode, entity_id=None):
|
||||
def set_operation_mode(hass, hvac_mode, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set new target operation mode."""
|
||||
data = {ATTR_HVAC_MODE: hvac_mode}
|
||||
|
||||
|
@ -187,7 +188,7 @@ def set_operation_mode(hass, hvac_mode, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_SET_HVAC_MODE, data)
|
||||
|
||||
|
||||
async def async_set_swing_mode(hass, swing_mode, entity_id=None):
|
||||
async def async_set_swing_mode(hass, swing_mode, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set new target swing mode."""
|
||||
data = {ATTR_SWING_MODE: swing_mode}
|
||||
|
||||
|
@ -198,7 +199,7 @@ async def async_set_swing_mode(hass, swing_mode, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def set_swing_mode(hass, swing_mode, entity_id=None):
|
||||
def set_swing_mode(hass, swing_mode, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set new target swing mode."""
|
||||
data = {ATTR_SWING_MODE: swing_mode}
|
||||
|
||||
|
@ -208,7 +209,7 @@ def set_swing_mode(hass, swing_mode, entity_id=None):
|
|||
hass.services.call(DOMAIN, SERVICE_SET_SWING_MODE, data)
|
||||
|
||||
|
||||
async def async_turn_on(hass, entity_id=None):
|
||||
async def async_turn_on(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn on device."""
|
||||
data = {}
|
||||
|
||||
|
@ -218,7 +219,7 @@ async def async_turn_on(hass, entity_id=None):
|
|||
await hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data, blocking=True)
|
||||
|
||||
|
||||
async def async_turn_off(hass, entity_id=None):
|
||||
async def async_turn_off(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn off device."""
|
||||
data = {}
|
||||
|
||||
|
|
|
@ -62,10 +62,14 @@ async def test_turn_off(hass):
|
|||
|
||||
async def test_turn_off_without_entity_id(hass):
|
||||
"""Test light turn off all lights."""
|
||||
await hass.services.async_call("light", "turn_on", {}, blocking=True)
|
||||
await hass.services.async_call(
|
||||
"light", "turn_on", {"entity_id": "all"}, blocking=True
|
||||
)
|
||||
|
||||
assert light.is_on(hass, ENTITY_LIGHT)
|
||||
|
||||
await hass.services.async_call("light", "turn_off", {}, blocking=True)
|
||||
await hass.services.async_call(
|
||||
"light", "turn_off", {"entity_id": "all"}, blocking=True
|
||||
)
|
||||
|
||||
assert not light.is_on(hass, ENTITY_LIGHT)
|
||||
|
|
|
@ -12,10 +12,15 @@ from homeassistant.components.fan import (
|
|||
SERVICE_SET_DIRECTION,
|
||||
SERVICE_SET_SPEED,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_ON, SERVICE_TURN_OFF
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_ON,
|
||||
SERVICE_TURN_OFF,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
|
||||
|
||||
async def async_turn_on(hass, entity_id: str = None, speed: str = None) -> None:
|
||||
async def async_turn_on(hass, entity_id=ENTITY_MATCH_ALL, speed: str = None) -> None:
|
||||
"""Turn all or specified fan on."""
|
||||
data = {
|
||||
key: value
|
||||
|
@ -26,7 +31,7 @@ async def async_turn_on(hass, entity_id: str = None, speed: str = None) -> None:
|
|||
await hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data, blocking=True)
|
||||
|
||||
|
||||
async def async_turn_off(hass, entity_id: str = None) -> None:
|
||||
async def async_turn_off(hass, entity_id=ENTITY_MATCH_ALL) -> None:
|
||||
"""Turn all or specified fan off."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
|
||||
|
@ -34,7 +39,7 @@ async def async_turn_off(hass, entity_id: str = None) -> None:
|
|||
|
||||
|
||||
async def async_oscillate(
|
||||
hass, entity_id: str = None, should_oscillate: bool = True
|
||||
hass, entity_id=ENTITY_MATCH_ALL, should_oscillate: bool = True
|
||||
) -> None:
|
||||
"""Set oscillation on all or specified fan."""
|
||||
data = {
|
||||
|
@ -49,7 +54,7 @@ async def async_oscillate(
|
|||
await hass.services.async_call(DOMAIN, SERVICE_OSCILLATE, data, blocking=True)
|
||||
|
||||
|
||||
async def async_set_speed(hass, entity_id: str = None, speed: str = None) -> None:
|
||||
async def async_set_speed(hass, entity_id=ENTITY_MATCH_ALL, speed: str = None) -> None:
|
||||
"""Set speed for all or specified fan."""
|
||||
data = {
|
||||
key: value
|
||||
|
@ -61,7 +66,7 @@ async def async_set_speed(hass, entity_id: str = None, speed: str = None) -> Non
|
|||
|
||||
|
||||
async def async_set_direction(
|
||||
hass, entity_id: str = None, direction: str = None
|
||||
hass, entity_id=ENTITY_MATCH_ALL, direction: str = None
|
||||
) -> None:
|
||||
"""Set direction for all or specified fan."""
|
||||
data = {
|
||||
|
|
|
@ -4,20 +4,20 @@ All containing methods are legacy helpers that should not be used by new
|
|||
components. Instead call the service directly.
|
||||
"""
|
||||
from homeassistant.components.image_processing import DOMAIN, SERVICE_SCAN
|
||||
from homeassistant.const import ATTR_ENTITY_ID
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ENTITY_MATCH_ALL
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
def scan(hass, entity_id=None):
|
||||
def scan(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Force process of all cameras or given entity."""
|
||||
hass.add_job(async_scan, hass, entity_id)
|
||||
|
||||
|
||||
@callback
|
||||
@bind_hass
|
||||
def async_scan(hass, entity_id=None):
|
||||
def async_scan(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Force process of all cameras or given entity."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_SCAN, data))
|
||||
|
|
|
@ -24,6 +24,7 @@ from homeassistant.const import (
|
|||
SERVICE_TOGGLE,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
@ -31,7 +32,7 @@ from homeassistant.loader import bind_hass
|
|||
@bind_hass
|
||||
def turn_on(
|
||||
hass,
|
||||
entity_id=None,
|
||||
entity_id=ENTITY_MATCH_ALL,
|
||||
transition=None,
|
||||
brightness=None,
|
||||
brightness_pct=None,
|
||||
|
@ -69,7 +70,7 @@ def turn_on(
|
|||
|
||||
async def async_turn_on(
|
||||
hass,
|
||||
entity_id=None,
|
||||
entity_id=ENTITY_MATCH_ALL,
|
||||
transition=None,
|
||||
brightness=None,
|
||||
brightness_pct=None,
|
||||
|
@ -110,12 +111,12 @@ async def async_turn_on(
|
|||
|
||||
|
||||
@bind_hass
|
||||
def turn_off(hass, entity_id=None, transition=None):
|
||||
def turn_off(hass, entity_id=ENTITY_MATCH_ALL, transition=None):
|
||||
"""Turn all or specified light off."""
|
||||
hass.add_job(async_turn_off, hass, entity_id, transition)
|
||||
|
||||
|
||||
async def async_turn_off(hass, entity_id=None, transition=None):
|
||||
async def async_turn_off(hass, entity_id=ENTITY_MATCH_ALL, transition=None):
|
||||
"""Turn all or specified light off."""
|
||||
data = {
|
||||
key: value
|
||||
|
@ -127,12 +128,12 @@ async def async_turn_off(hass, entity_id=None, transition=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def toggle(hass, entity_id=None, transition=None):
|
||||
def toggle(hass, entity_id=ENTITY_MATCH_ALL, transition=None):
|
||||
"""Toggle all or specified light."""
|
||||
hass.add_job(async_toggle, hass, entity_id, transition)
|
||||
|
||||
|
||||
async def async_toggle(hass, entity_id=None, transition=None):
|
||||
async def async_toggle(hass, entity_id=ENTITY_MATCH_ALL, transition=None):
|
||||
"""Toggle all or specified light."""
|
||||
data = {
|
||||
key: value
|
||||
|
|
|
@ -10,12 +10,13 @@ from homeassistant.const import (
|
|||
SERVICE_LOCK,
|
||||
SERVICE_UNLOCK,
|
||||
SERVICE_OPEN,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
def lock(hass, entity_id=None, code=None):
|
||||
def lock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
|
||||
"""Lock all or specified locks."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -26,7 +27,7 @@ def lock(hass, entity_id=None, code=None):
|
|||
hass.services.call(DOMAIN, SERVICE_LOCK, data)
|
||||
|
||||
|
||||
async def async_lock(hass, entity_id=None, code=None):
|
||||
async def async_lock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
|
||||
"""Lock all or specified locks."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -38,7 +39,7 @@ async def async_lock(hass, entity_id=None, code=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def unlock(hass, entity_id=None, code=None):
|
||||
def unlock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
|
||||
"""Unlock all or specified locks."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -49,7 +50,7 @@ def unlock(hass, entity_id=None, code=None):
|
|||
hass.services.call(DOMAIN, SERVICE_UNLOCK, data)
|
||||
|
||||
|
||||
async def async_unlock(hass, entity_id=None, code=None):
|
||||
async def async_unlock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
|
||||
"""Lock all or specified locks."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -61,7 +62,7 @@ async def async_unlock(hass, entity_id=None, code=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def open_lock(hass, entity_id=None, code=None):
|
||||
def open_lock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
|
||||
"""Open all or specified locks."""
|
||||
data = {}
|
||||
if code:
|
||||
|
@ -72,7 +73,7 @@ def open_lock(hass, entity_id=None, code=None):
|
|||
hass.services.call(DOMAIN, SERVICE_OPEN, data)
|
||||
|
||||
|
||||
async def async_open_lock(hass, entity_id=None, code=None):
|
||||
async def async_open_lock(hass, entity_id=ENTITY_MATCH_ALL, code=None):
|
||||
"""Lock all or specified locks."""
|
||||
data = {}
|
||||
if code:
|
||||
|
|
|
@ -32,47 +32,48 @@ from homeassistant.const import (
|
|||
SERVICE_VOLUME_MUTE,
|
||||
SERVICE_VOLUME_SET,
|
||||
SERVICE_VOLUME_UP,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
def turn_on(hass, entity_id=None):
|
||||
def turn_on(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn on specified media player or all."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_TURN_ON, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def turn_off(hass, entity_id=None):
|
||||
def turn_off(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn off specified media player or all."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_TURN_OFF, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def toggle(hass, entity_id=None):
|
||||
def toggle(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Toggle specified media player or all."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_TOGGLE, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def volume_up(hass, entity_id=None):
|
||||
def volume_up(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for volume up."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_VOLUME_UP, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def volume_down(hass, entity_id=None):
|
||||
def volume_down(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for volume down."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_VOLUME_DOWN, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def mute_volume(hass, mute, entity_id=None):
|
||||
def mute_volume(hass, mute, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for muting the volume."""
|
||||
data = {ATTR_MEDIA_VOLUME_MUTED: mute}
|
||||
|
||||
|
@ -83,7 +84,7 @@ def mute_volume(hass, mute, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def set_volume_level(hass, volume, entity_id=None):
|
||||
def set_volume_level(hass, volume, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for setting the volume."""
|
||||
data = {ATTR_MEDIA_VOLUME_LEVEL: volume}
|
||||
|
||||
|
@ -94,49 +95,49 @@ def set_volume_level(hass, volume, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def media_play_pause(hass, entity_id=None):
|
||||
def media_play_pause(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for play/pause."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_MEDIA_PLAY_PAUSE, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def media_play(hass, entity_id=None):
|
||||
def media_play(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for play/pause."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_MEDIA_PLAY, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def media_pause(hass, entity_id=None):
|
||||
def media_pause(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for pause."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_MEDIA_PAUSE, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def media_stop(hass, entity_id=None):
|
||||
def media_stop(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for stop."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_MEDIA_STOP, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def media_next_track(hass, entity_id=None):
|
||||
def media_next_track(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for next track."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_MEDIA_NEXT_TRACK, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def media_previous_track(hass, entity_id=None):
|
||||
def media_previous_track(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for prev track."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_MEDIA_PREVIOUS_TRACK, data)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def media_seek(hass, position, entity_id=None):
|
||||
def media_seek(hass, position, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command to seek in current playing media."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
data[ATTR_MEDIA_SEEK_POSITION] = position
|
||||
|
@ -144,7 +145,7 @@ def media_seek(hass, position, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def play_media(hass, media_type, media_id, entity_id=None, enqueue=None):
|
||||
def play_media(hass, media_type, media_id, entity_id=ENTITY_MATCH_ALL, enqueue=None):
|
||||
"""Send the media player the command for playing media."""
|
||||
data = {ATTR_MEDIA_CONTENT_TYPE: media_type, ATTR_MEDIA_CONTENT_ID: media_id}
|
||||
|
||||
|
@ -158,7 +159,7 @@ def play_media(hass, media_type, media_id, entity_id=None, enqueue=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def select_source(hass, source, entity_id=None):
|
||||
def select_source(hass, source, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command to select input source."""
|
||||
data = {ATTR_INPUT_SOURCE: source}
|
||||
|
||||
|
@ -169,7 +170,7 @@ def select_source(hass, source, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def clear_playlist(hass, entity_id=None):
|
||||
def clear_playlist(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the media player the command for clear playlist."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
hass.services.call(DOMAIN, SERVICE_CLEAR_PLAYLIST, data)
|
||||
|
|
|
@ -28,6 +28,7 @@ from homeassistant.const import (
|
|||
CONF_PLATFORM,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
|
@ -75,29 +76,41 @@ async def test_all_commands(hass, mqtt_mock):
|
|||
|
||||
assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config})
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_START, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_START, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_called_once_with(COMMAND_TOPIC, "start", 0, False)
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_STOP, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_STOP, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_called_once_with(COMMAND_TOPIC, "stop", 0, False)
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_PAUSE, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_PAUSE, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_called_once_with(COMMAND_TOPIC, "pause", 0, False)
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_LOCATE, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_LOCATE, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_called_once_with(COMMAND_TOPIC, "locate", 0, False)
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_CLEAN_SPOT, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_CLEAN_SPOT, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
COMMAND_TOPIC, "clean_spot", 0, False
|
||||
)
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_RETURN_TO_BASE, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_RETURN_TO_BASE, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
COMMAND_TOPIC, "return_to_base", 0, False
|
||||
)
|
||||
|
@ -134,27 +147,39 @@ async def test_commands_without_supported_features(hass, mqtt_mock):
|
|||
|
||||
assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config})
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_START, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_START, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_not_called()
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_PAUSE, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_PAUSE, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_not_called()
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_STOP, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_STOP, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_not_called()
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_RETURN_TO_BASE, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_RETURN_TO_BASE, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_not_called()
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_LOCATE, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_LOCATE, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_not_called()
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
await hass.services.async_call(DOMAIN, SERVICE_CLEAN_SPOT, blocking=True)
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_CLEAN_SPOT, {"entity_id": ENTITY_MATCH_ALL}, blocking=True
|
||||
)
|
||||
mqtt_mock.async_publish.assert_not_called()
|
||||
mqtt_mock.async_publish.reset_mock()
|
||||
|
||||
|
|
|
@ -15,12 +15,17 @@ from homeassistant.components.remote import (
|
|||
SERVICE_LEARN_COMMAND,
|
||||
SERVICE_SEND_COMMAND,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
def turn_on(hass, activity=None, entity_id=None):
|
||||
def turn_on(hass, activity=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified remote on."""
|
||||
data = {
|
||||
key: value
|
||||
|
@ -31,7 +36,7 @@ def turn_on(hass, activity=None, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def turn_off(hass, activity=None, entity_id=None):
|
||||
def turn_off(hass, activity=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified remote off."""
|
||||
data = {}
|
||||
if activity:
|
||||
|
@ -45,7 +50,12 @@ def turn_off(hass, activity=None, entity_id=None):
|
|||
|
||||
@bind_hass
|
||||
def send_command(
|
||||
hass, command, entity_id=None, device=None, num_repeats=None, delay_secs=None
|
||||
hass,
|
||||
command,
|
||||
entity_id=ENTITY_MATCH_ALL,
|
||||
device=None,
|
||||
num_repeats=None,
|
||||
delay_secs=None,
|
||||
):
|
||||
"""Send a command to a device."""
|
||||
data = {ATTR_COMMAND: command}
|
||||
|
@ -66,7 +76,12 @@ def send_command(
|
|||
|
||||
@bind_hass
|
||||
def learn_command(
|
||||
hass, entity_id=None, device=None, command=None, alternative=None, timeout=None
|
||||
hass,
|
||||
entity_id=ENTITY_MATCH_ALL,
|
||||
device=None,
|
||||
command=None,
|
||||
alternative=None,
|
||||
timeout=None,
|
||||
):
|
||||
"""Learn a command from a device."""
|
||||
data = {}
|
||||
|
|
|
@ -4,12 +4,12 @@ All containing methods are legacy helpers that should not be used by new
|
|||
components. Instead call the service directly.
|
||||
"""
|
||||
from homeassistant.components.scene import DOMAIN
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_ON
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_ON, ENTITY_MATCH_ALL
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
def activate(hass, entity_id=None):
|
||||
def activate(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Activate a scene."""
|
||||
data = {}
|
||||
|
||||
|
|
|
@ -551,7 +551,9 @@ async def test_set_turn_off(hass, air_conditioner):
|
|||
await setup_platform(hass, CLIMATE_DOMAIN, devices=[air_conditioner])
|
||||
state = hass.states.get("climate.air_conditioner")
|
||||
assert state.state == HVAC_MODE_HEAT_COOL
|
||||
await hass.services.async_call(CLIMATE_DOMAIN, SERVICE_TURN_OFF, blocking=True)
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN, SERVICE_TURN_OFF, {"entity_id": "all"}, blocking=True
|
||||
)
|
||||
state = hass.states.get("climate.air_conditioner")
|
||||
assert state.state == HVAC_MODE_OFF
|
||||
|
||||
|
@ -562,7 +564,9 @@ async def test_set_turn_on(hass, air_conditioner):
|
|||
await setup_platform(hass, CLIMATE_DOMAIN, devices=[air_conditioner])
|
||||
state = hass.states.get("climate.air_conditioner")
|
||||
assert state.state == HVAC_MODE_OFF
|
||||
await hass.services.async_call(CLIMATE_DOMAIN, SERVICE_TURN_ON, blocking=True)
|
||||
await hass.services.async_call(
|
||||
CLIMATE_DOMAIN, SERVICE_TURN_ON, {"entity_id": "all"}, blocking=True
|
||||
)
|
||||
state = hass.states.get("climate.air_conditioner")
|
||||
assert state.state == HVAC_MODE_HEAT_COOL
|
||||
|
||||
|
|
|
@ -114,7 +114,10 @@ async def test_set_cover_position(hass, device_factory):
|
|||
await setup_platform(hass, COVER_DOMAIN, devices=[device])
|
||||
# Act
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN, SERVICE_SET_COVER_POSITION, {ATTR_POSITION: 50}, blocking=True
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{ATTR_POSITION: 50, "entity_id": "all"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get("cover.shade")
|
||||
|
@ -136,7 +139,10 @@ async def test_set_cover_position_unsupported(hass, device_factory):
|
|||
await setup_platform(hass, COVER_DOMAIN, devices=[device])
|
||||
# Act
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN, SERVICE_SET_COVER_POSITION, {ATTR_POSITION: 50}, blocking=True
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{"entity_id": "all", ATTR_POSITION: 50},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
state = hass.states.get("cover.shade")
|
||||
|
|
|
@ -4,29 +4,34 @@ All containing methods are legacy helpers that should not be used by new
|
|||
components. Instead call the service directly.
|
||||
"""
|
||||
from homeassistant.components.switch import DOMAIN
|
||||
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
def turn_on(hass, entity_id=None):
|
||||
def turn_on(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified switch on."""
|
||||
hass.add_job(async_turn_on, hass, entity_id)
|
||||
|
||||
|
||||
async def async_turn_on(hass, entity_id=None):
|
||||
async def async_turn_on(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified switch on."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def turn_off(hass, entity_id=None):
|
||||
def turn_off(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified switch off."""
|
||||
hass.add_job(async_turn_off, hass, entity_id)
|
||||
|
||||
|
||||
async def async_turn_off(hass, entity_id=None):
|
||||
async def async_turn_off(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified switch off."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TURN_OFF, data, blocking=True)
|
||||
|
|
|
@ -23,137 +23,138 @@ from homeassistant.const import (
|
|||
SERVICE_TOGGLE,
|
||||
SERVICE_TURN_OFF,
|
||||
SERVICE_TURN_ON,
|
||||
ENTITY_MATCH_ALL,
|
||||
)
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
def turn_on(hass, entity_id=None):
|
||||
def turn_on(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified vacuum on."""
|
||||
hass.add_job(async_turn_on, hass, entity_id)
|
||||
|
||||
|
||||
async def async_turn_on(hass, entity_id=None):
|
||||
async def async_turn_on(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified vacuum on."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TURN_ON, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def turn_off(hass, entity_id=None):
|
||||
def turn_off(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified vacuum off."""
|
||||
hass.add_job(async_turn_off, hass, entity_id)
|
||||
|
||||
|
||||
async def async_turn_off(hass, entity_id=None):
|
||||
async def async_turn_off(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified vacuum off."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TURN_OFF, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def toggle(hass, entity_id=None):
|
||||
def toggle(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Toggle all or specified vacuum."""
|
||||
hass.add_job(async_toggle, hass, entity_id)
|
||||
|
||||
|
||||
async def async_toggle(hass, entity_id=None):
|
||||
async def async_toggle(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Toggle all or specified vacuum."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_TOGGLE, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def locate(hass, entity_id=None):
|
||||
def locate(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Locate all or specified vacuum."""
|
||||
hass.add_job(async_locate, hass, entity_id)
|
||||
|
||||
|
||||
async def async_locate(hass, entity_id=None):
|
||||
async def async_locate(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Locate all or specified vacuum."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_LOCATE, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def clean_spot(hass, entity_id=None):
|
||||
def clean_spot(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or specified vacuum to perform a spot clean-up."""
|
||||
hass.add_job(async_clean_spot, hass, entity_id)
|
||||
|
||||
|
||||
async def async_clean_spot(hass, entity_id=None):
|
||||
async def async_clean_spot(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or specified vacuum to perform a spot clean-up."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_CLEAN_SPOT, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def return_to_base(hass, entity_id=None):
|
||||
def return_to_base(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or specified vacuum to return to base."""
|
||||
hass.add_job(async_return_to_base, hass, entity_id)
|
||||
|
||||
|
||||
async def async_return_to_base(hass, entity_id=None):
|
||||
async def async_return_to_base(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or specified vacuum to return to base."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_RETURN_TO_BASE, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def start_pause(hass, entity_id=None):
|
||||
def start_pause(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or specified vacuum to start or pause the current task."""
|
||||
hass.add_job(async_start_pause, hass, entity_id)
|
||||
|
||||
|
||||
async def async_start_pause(hass, entity_id=None):
|
||||
async def async_start_pause(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or specified vacuum to start or pause the current task."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_START_PAUSE, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def start(hass, entity_id=None):
|
||||
def start(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or specified vacuum to start or resume the current task."""
|
||||
hass.add_job(async_start, hass, entity_id)
|
||||
|
||||
|
||||
async def async_start(hass, entity_id=None):
|
||||
async def async_start(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or specified vacuum to start or resume the current task."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_START, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def pause(hass, entity_id=None):
|
||||
def pause(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or the specified vacuum to pause the current task."""
|
||||
hass.add_job(async_pause, hass, entity_id)
|
||||
|
||||
|
||||
async def async_pause(hass, entity_id=None):
|
||||
async def async_pause(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Tell all or the specified vacuum to pause the current task."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_PAUSE, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def stop(hass, entity_id=None):
|
||||
def stop(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Stop all or specified vacuum."""
|
||||
hass.add_job(async_stop, hass, entity_id)
|
||||
|
||||
|
||||
async def async_stop(hass, entity_id=None):
|
||||
async def async_stop(hass, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Stop all or specified vacuum."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else None
|
||||
await hass.services.async_call(DOMAIN, SERVICE_STOP, data, blocking=True)
|
||||
|
||||
|
||||
@bind_hass
|
||||
def set_fan_speed(hass, fan_speed, entity_id=None):
|
||||
def set_fan_speed(hass, fan_speed, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set fan speed for all or specified vacuum."""
|
||||
hass.add_job(async_set_fan_speed, hass, fan_speed, entity_id)
|
||||
|
||||
|
||||
async def async_set_fan_speed(hass, fan_speed, entity_id=None):
|
||||
async def async_set_fan_speed(hass, fan_speed, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set fan speed for all or specified vacuum."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
data[ATTR_FAN_SPEED] = fan_speed
|
||||
|
@ -161,12 +162,12 @@ async def async_set_fan_speed(hass, fan_speed, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def send_command(hass, command, params=None, entity_id=None):
|
||||
def send_command(hass, command, params=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send command to all or specified vacuum."""
|
||||
hass.add_job(async_send_command, hass, command, params, entity_id)
|
||||
|
||||
|
||||
async def async_send_command(hass, command, params=None, entity_id=None):
|
||||
async def async_send_command(hass, command, params=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send command to all or specified vacuum."""
|
||||
data = {ATTR_ENTITY_ID: entity_id} if entity_id else {}
|
||||
data[ATTR_COMMAND] = command
|
||||
|
|
|
@ -12,12 +12,12 @@ from homeassistant.components.water_heater import (
|
|||
SERVICE_SET_TEMPERATURE,
|
||||
SERVICE_SET_OPERATION_MODE,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE, ENTITY_MATCH_ALL
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
||||
@bind_hass
|
||||
def set_away_mode(hass, away_mode, entity_id=None):
|
||||
def set_away_mode(hass, away_mode, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Turn all or specified water_heater devices away mode on."""
|
||||
data = {ATTR_AWAY_MODE: away_mode}
|
||||
|
||||
|
@ -28,7 +28,9 @@ def set_away_mode(hass, away_mode, entity_id=None):
|
|||
|
||||
|
||||
@bind_hass
|
||||
def set_temperature(hass, temperature=None, entity_id=None, operation_mode=None):
|
||||
def set_temperature(
|
||||
hass, temperature=None, entity_id=ENTITY_MATCH_ALL, operation_mode=None
|
||||
):
|
||||
"""Set new target temperature."""
|
||||
kwargs = {
|
||||
key: value
|
||||
|
@ -44,7 +46,7 @@ def set_temperature(hass, temperature=None, entity_id=None, operation_mode=None)
|
|||
|
||||
|
||||
@bind_hass
|
||||
def set_operation_mode(hass, operation_mode, entity_id=None):
|
||||
def set_operation_mode(hass, operation_mode, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Set new target operation mode."""
|
||||
data = {ATTR_OPERATION_MODE: operation_mode}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import asynctest
|
|||
import pytest
|
||||
|
||||
import homeassistant.core as ha
|
||||
from homeassistant.const import ENTITY_MATCH_ALL
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
from homeassistant.components import group
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
|
@ -194,7 +195,7 @@ async def test_extract_from_service_available_device(hass):
|
|||
]
|
||||
)
|
||||
|
||||
call_1 = ha.ServiceCall("test", "service")
|
||||
call_1 = ha.ServiceCall("test", "service", data={"entity_id": ENTITY_MATCH_ALL})
|
||||
|
||||
assert ["test_domain.test_1", "test_domain.test_3"] == sorted(
|
||||
ent.entity_id for ent in (await component.async_extract_from_service(call_1))
|
||||
|
@ -250,7 +251,7 @@ async def test_platform_not_ready(hass):
|
|||
assert "test_domain.mod1" in hass.config.components
|
||||
|
||||
|
||||
async def test_extract_from_service_returns_all_if_no_entity_id(hass):
|
||||
async def test_extract_from_service_fails_if_no_entity_id(hass):
|
||||
"""Test the extraction of everything from service."""
|
||||
component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||
await component.async_add_entities(
|
||||
|
@ -259,7 +260,7 @@ async def test_extract_from_service_returns_all_if_no_entity_id(hass):
|
|||
|
||||
call = ha.ServiceCall("test", "service")
|
||||
|
||||
assert ["test_domain.test_1", "test_domain.test_2"] == sorted(
|
||||
assert [] == sorted(
|
||||
ent.entity_id for ent in (await component.async_extract_from_service(call))
|
||||
)
|
||||
|
||||
|
@ -445,12 +446,9 @@ async def test_extract_all_omit_entity_id(hass, caplog):
|
|||
|
||||
call = ha.ServiceCall("test", "service")
|
||||
|
||||
assert ["test_domain.test_1", "test_domain.test_2"] == sorted(
|
||||
assert [] == sorted(
|
||||
ent.entity_id for ent in await 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):
|
||||
|
|
|
@ -11,7 +11,7 @@ import pytest
|
|||
# To prevent circular import when running just this file
|
||||
import homeassistant.components # noqa: F401
|
||||
from homeassistant import core as ha, exceptions
|
||||
from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ENTITY_ID
|
||||
from homeassistant.const import STATE_ON, STATE_OFF, ATTR_ENTITY_ID, ENTITY_MATCH_ALL
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.auth.permissions import PolicyPermissions
|
||||
|
@ -334,7 +334,10 @@ async def test_call_context_target_all(hass, mock_service_platform_call, mock_en
|
|||
[Mock(entities=mock_entities)],
|
||||
Mock(),
|
||||
ha.ServiceCall(
|
||||
"test_domain", "test_service", context=ha.Context(user_id="mock-id")
|
||||
"test_domain",
|
||||
"test_service",
|
||||
data={"entity_id": ENTITY_MATCH_ALL},
|
||||
context=ha.Context(user_id="mock-id"),
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -407,7 +410,9 @@ async def test_call_no_context_target_all(
|
|||
hass,
|
||||
[Mock(entities=mock_entities)],
|
||||
Mock(),
|
||||
ha.ServiceCall("test_domain", "test_service"),
|
||||
ha.ServiceCall(
|
||||
"test_domain", "test_service", data={"entity_id": ENTITY_MATCH_ALL}
|
||||
),
|
||||
)
|
||||
|
||||
assert len(mock_service_platform_call.mock_calls) == 1
|
||||
|
@ -458,9 +463,9 @@ async def test_call_with_match_all(
|
|||
|
||||
|
||||
async def test_call_with_omit_entity_id(
|
||||
hass, mock_service_platform_call, mock_entities, caplog
|
||||
hass, mock_service_platform_call, mock_entities
|
||||
):
|
||||
"""Check we only target allowed entities if targetting all."""
|
||||
"""Check service call if we do not pass an entity ID."""
|
||||
await service.entity_service_call(
|
||||
hass,
|
||||
[Mock(entities=mock_entities)],
|
||||
|
@ -470,13 +475,7 @@ async def test_call_with_omit_entity_id(
|
|||
|
||||
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
|
||||
assert entities == []
|
||||
|
||||
|
||||
async def test_register_admin_service(hass, hass_read_only_user, hass_admin_user):
|
||||
|
|
Loading…
Add table
Reference in a new issue