mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Teach call service script action about entity registry ids (#61172)
This commit is contained in:
parent
d5d8eefded
commit
fc2025509e
@ -311,6 +311,12 @@ comp_entity_ids = vol.Any(
|
||||
)
|
||||
|
||||
|
||||
comp_entity_ids_or_uuids = vol.Any(
|
||||
vol.All(vol.Lower, vol.Any(ENTITY_MATCH_ALL, ENTITY_MATCH_NONE)),
|
||||
entity_ids_or_uuids,
|
||||
)
|
||||
|
||||
|
||||
def entity_domain(domain: str | list[str]) -> Callable[[Any], str]:
|
||||
"""Validate that entity belong to domain."""
|
||||
ent_domain = entities_domain(domain)
|
||||
@ -972,6 +978,23 @@ ENTITY_SERVICE_FIELDS = {
|
||||
),
|
||||
}
|
||||
|
||||
TARGET_SERVICE_FIELDS = {
|
||||
# Same as ENTITY_SERVICE_FIELDS but supports specifying entity by entity registry
|
||||
# ID.
|
||||
# Either accept static entity IDs, a single dynamic template or a mixed list
|
||||
# of static and dynamic templates. While this could be solved with a single
|
||||
# complex template, handling it like this, keeps config validation useful.
|
||||
vol.Optional(ATTR_ENTITY_ID): vol.Any(
|
||||
comp_entity_ids_or_uuids, dynamic_template, vol.All(list, template_complex)
|
||||
),
|
||||
vol.Optional(ATTR_DEVICE_ID): vol.Any(
|
||||
ENTITY_MATCH_NONE, vol.All(ensure_list, [vol.Any(dynamic_template, str)])
|
||||
),
|
||||
vol.Optional(ATTR_AREA_ID): vol.Any(
|
||||
ENTITY_MATCH_NONE, vol.All(ensure_list, [vol.Any(dynamic_template, str)])
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def make_entity_service_schema(
|
||||
schema: dict, *, extra: int = vol.PREVENT_EXTRA
|
||||
@ -1034,7 +1057,7 @@ SERVICE_SCHEMA = vol.All(
|
||||
template, vol.All(dict, template_complex)
|
||||
),
|
||||
vol.Optional(CONF_ENTITY_ID): comp_entity_ids,
|
||||
vol.Optional(CONF_TARGET): vol.Any(ENTITY_SERVICE_FIELDS, dynamic_template),
|
||||
vol.Optional(CONF_TARGET): vol.Any(TARGET_SERVICE_FIELDS, dynamic_template),
|
||||
}
|
||||
),
|
||||
has_at_least_one_key(CONF_SERVICE, CONF_SERVICE_TEMPLATE),
|
||||
|
@ -218,7 +218,10 @@ def async_prepare_call_from_config(
|
||||
target.update(template.render_complex(conf, variables))
|
||||
|
||||
if CONF_ENTITY_ID in target:
|
||||
target[CONF_ENTITY_ID] = cv.comp_entity_ids(target[CONF_ENTITY_ID])
|
||||
registry = entity_registry.async_get(hass)
|
||||
target[CONF_ENTITY_ID] = entity_registry.async_resolve_entity_ids(
|
||||
registry, cv.comp_entity_ids_or_uuids(target[CONF_ENTITY_ID])
|
||||
)
|
||||
except TemplateError as ex:
|
||||
raise HomeAssistantError(
|
||||
f"Error rendering service target template: {ex}"
|
||||
|
@ -29,6 +29,7 @@ from homeassistant.setup import async_setup_component
|
||||
|
||||
from tests.common import (
|
||||
MockEntity,
|
||||
async_mock_service,
|
||||
get_test_home_assistant,
|
||||
mock_device_registry,
|
||||
mock_registry,
|
||||
@ -375,6 +376,27 @@ class TestServiceHelpers(unittest.TestCase):
|
||||
assert mock_log.call_count == 3
|
||||
|
||||
|
||||
async def test_service_call_entry_id(hass):
|
||||
"""Test service call with entity specified by entity registry ID."""
|
||||
registry = ent_reg.async_get(hass)
|
||||
calls = async_mock_service(hass, "test_domain", "test_service")
|
||||
entry = registry.async_get_or_create(
|
||||
"hello", "hue", "1234", suggested_object_id="world"
|
||||
)
|
||||
|
||||
assert entry.entity_id == "hello.world"
|
||||
|
||||
config = {
|
||||
"service": "test_domain.test_service",
|
||||
"target": {"entity_id": entry.id},
|
||||
}
|
||||
|
||||
await service.async_call_from_config(hass, config)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert dict(calls[0].data) == {"entity_id": ["hello.world"]}
|
||||
|
||||
|
||||
async def test_extract_entity_ids(hass):
|
||||
"""Test extract_entity_ids method."""
|
||||
hass.states.async_set("light.Bowl", STATE_ON)
|
||||
|
Loading…
x
Reference in New Issue
Block a user