mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Teach search about blueprints (#78535)
This commit is contained in:
parent
24e1243da7
commit
d05d67414a
@ -228,6 +228,20 @@ def automations_with_blueprint(hass: HomeAssistant, blueprint_path: str) -> list
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def blueprint_in_automation(hass: HomeAssistant, entity_id: str) -> str | None:
|
||||||
|
"""Return the blueprint the automation is based on or None."""
|
||||||
|
if DOMAIN not in hass.data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
component: EntityComponent[AutomationEntity] = hass.data[DOMAIN]
|
||||||
|
|
||||||
|
if (automation_entity := component.get_entity(entity_id)) is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return automation_entity.referenced_blueprint
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
"""Set up all automations."""
|
"""Set up all automations."""
|
||||||
hass.data[DOMAIN] = component = EntityComponent[AutomationEntity](
|
hass.data[DOMAIN] = component = EntityComponent[AutomationEntity](
|
||||||
|
@ -160,6 +160,20 @@ def scripts_with_blueprint(hass: HomeAssistant, blueprint_path: str) -> list[str
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def blueprint_in_script(hass: HomeAssistant, entity_id: str) -> str | None:
|
||||||
|
"""Return the blueprint the script is based on or None."""
|
||||||
|
if DOMAIN not in hass.data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
component: EntityComponent[ScriptEntity] = hass.data[DOMAIN]
|
||||||
|
|
||||||
|
if (script_entity := component.get_entity(entity_id)) is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return script_entity.referenced_blueprint
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
"""Load the scripts from the configuration."""
|
"""Load the scripts from the configuration."""
|
||||||
hass.data[DOMAIN] = component = EntityComponent[ScriptEntity](LOGGER, DOMAIN, hass)
|
hass.data[DOMAIN] = component = EntityComponent[ScriptEntity](LOGGER, DOMAIN, hass)
|
||||||
|
@ -37,7 +37,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
(
|
(
|
||||||
"area",
|
"area",
|
||||||
"automation",
|
"automation",
|
||||||
"blueprint",
|
"automation_blueprint",
|
||||||
"config_entry",
|
"config_entry",
|
||||||
"device",
|
"device",
|
||||||
"entity",
|
"entity",
|
||||||
@ -45,6 +45,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
"person",
|
"person",
|
||||||
"scene",
|
"scene",
|
||||||
"script",
|
"script",
|
||||||
|
"script_blueprint",
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
vol.Required("item_id"): str,
|
vol.Required("item_id"): str,
|
||||||
@ -81,10 +82,12 @@ class Searcher:
|
|||||||
DONT_RESOLVE = {
|
DONT_RESOLVE = {
|
||||||
"area",
|
"area",
|
||||||
"automation",
|
"automation",
|
||||||
|
"automation_blueprint",
|
||||||
"config_entry",
|
"config_entry",
|
||||||
"group",
|
"group",
|
||||||
"scene",
|
"scene",
|
||||||
"script",
|
"script",
|
||||||
|
"script_blueprint",
|
||||||
}
|
}
|
||||||
# These types exist as an entity and so need cleanup in results
|
# These types exist as an entity and so need cleanup in results
|
||||||
EXIST_AS_ENTITY = {"automation", "group", "person", "scene", "script"}
|
EXIST_AS_ENTITY = {"automation", "group", "person", "scene", "script"}
|
||||||
@ -176,6 +179,22 @@ class Searcher:
|
|||||||
for area in automation.areas_in_automation(self.hass, automation_entity_id):
|
for area in automation.areas_in_automation(self.hass, automation_entity_id):
|
||||||
self._add_or_resolve("area", area)
|
self._add_or_resolve("area", area)
|
||||||
|
|
||||||
|
if blueprint := automation.blueprint_in_automation(
|
||||||
|
self.hass, automation_entity_id
|
||||||
|
):
|
||||||
|
self._add_or_resolve("automation_blueprint", blueprint)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _resolve_automation_blueprint(self, blueprint_path) -> None:
|
||||||
|
"""Resolve an automation blueprint.
|
||||||
|
|
||||||
|
Will only be called if blueprint is an entry point.
|
||||||
|
"""
|
||||||
|
for entity_id in automation.automations_with_blueprint(
|
||||||
|
self.hass, blueprint_path
|
||||||
|
):
|
||||||
|
self._add_or_resolve("automation", entity_id)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _resolve_config_entry(self, config_entry_id) -> None:
|
def _resolve_config_entry(self, config_entry_id) -> None:
|
||||||
"""Resolve a config entry.
|
"""Resolve a config entry.
|
||||||
@ -295,3 +314,15 @@ class Searcher:
|
|||||||
|
|
||||||
for area in script.areas_in_script(self.hass, script_entity_id):
|
for area in script.areas_in_script(self.hass, script_entity_id):
|
||||||
self._add_or_resolve("area", area)
|
self._add_or_resolve("area", area)
|
||||||
|
|
||||||
|
if blueprint := script.blueprint_in_script(self.hass, script_entity_id):
|
||||||
|
self._add_or_resolve("script_blueprint", blueprint)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _resolve_script_blueprint(self, blueprint_path) -> None:
|
||||||
|
"""Resolve a script blueprint.
|
||||||
|
|
||||||
|
Will only be called if blueprint is an entry point.
|
||||||
|
"""
|
||||||
|
for entity_id in script.scripts_with_blueprint(self.hass, blueprint_path):
|
||||||
|
self._add_or_resolve("script", entity_id)
|
||||||
|
@ -449,6 +449,113 @@ async def test_person_lookup(hass: HomeAssistant) -> None:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_automation_blueprint(hass):
|
||||||
|
"""Test searching for automation blueprints."""
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"automation",
|
||||||
|
{
|
||||||
|
"automation": [
|
||||||
|
{
|
||||||
|
"alias": "blueprint_automation_1",
|
||||||
|
"trigger": {"platform": "template", "value_template": "true"},
|
||||||
|
"use_blueprint": {
|
||||||
|
"path": "test_event_service.yaml",
|
||||||
|
"input": {
|
||||||
|
"trigger_event": "blueprint_event_1",
|
||||||
|
"service_to_call": "test.automation_1",
|
||||||
|
"a_number": 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": "blueprint_automation_2",
|
||||||
|
"trigger": {"platform": "template", "value_template": "true"},
|
||||||
|
"use_blueprint": {
|
||||||
|
"path": "test_event_service.yaml",
|
||||||
|
"input": {
|
||||||
|
"trigger_event": "blueprint_event_2",
|
||||||
|
"service_to_call": "test.automation_2",
|
||||||
|
"a_number": 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure automations set up correctly.
|
||||||
|
assert hass.states.get("automation.blueprint_automation_1") is not None
|
||||||
|
assert hass.states.get("automation.blueprint_automation_1") is not None
|
||||||
|
|
||||||
|
device_reg = dr.async_get(hass)
|
||||||
|
entity_reg = er.async_get(hass)
|
||||||
|
|
||||||
|
searcher = search.Searcher(hass, device_reg, entity_reg, MOCK_ENTITY_SOURCES)
|
||||||
|
assert searcher.async_search("automation", "automation.blueprint_automation_1") == {
|
||||||
|
"automation": {"automation.blueprint_automation_2"},
|
||||||
|
"automation_blueprint": {"test_event_service.yaml"},
|
||||||
|
"entity": {"light.kitchen"},
|
||||||
|
}
|
||||||
|
|
||||||
|
searcher = search.Searcher(hass, device_reg, entity_reg, MOCK_ENTITY_SOURCES)
|
||||||
|
assert searcher.async_search("automation_blueprint", "test_event_service.yaml") == {
|
||||||
|
"automation": {
|
||||||
|
"automation.blueprint_automation_1",
|
||||||
|
"automation.blueprint_automation_2",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_script_blueprint(hass):
|
||||||
|
"""Test searching for script blueprints."""
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"script",
|
||||||
|
{
|
||||||
|
"script": {
|
||||||
|
"blueprint_script_1": {
|
||||||
|
"use_blueprint": {
|
||||||
|
"path": "test_service.yaml",
|
||||||
|
"input": {
|
||||||
|
"service_to_call": "test.automation",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"blueprint_script_2": {
|
||||||
|
"use_blueprint": {
|
||||||
|
"path": "test_service.yaml",
|
||||||
|
"input": {
|
||||||
|
"service_to_call": "test.automation",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure automations set up correctly.
|
||||||
|
assert hass.states.get("script.blueprint_script_1") is not None
|
||||||
|
assert hass.states.get("script.blueprint_script_1") is not None
|
||||||
|
|
||||||
|
device_reg = dr.async_get(hass)
|
||||||
|
entity_reg = er.async_get(hass)
|
||||||
|
|
||||||
|
searcher = search.Searcher(hass, device_reg, entity_reg, MOCK_ENTITY_SOURCES)
|
||||||
|
assert searcher.async_search("script", "script.blueprint_script_1") == {
|
||||||
|
"entity": {"light.kitchen"},
|
||||||
|
"script": {"script.blueprint_script_2"},
|
||||||
|
"script_blueprint": {"test_service.yaml"},
|
||||||
|
}
|
||||||
|
|
||||||
|
searcher = search.Searcher(hass, device_reg, entity_reg, MOCK_ENTITY_SOURCES)
|
||||||
|
assert searcher.async_search("script_blueprint", "test_service.yaml") == {
|
||||||
|
"script": {"script.blueprint_script_1", "script.blueprint_script_2"},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_ws_api(hass: HomeAssistant, hass_ws_client: WebSocketGenerator) -> None:
|
async def test_ws_api(hass: HomeAssistant, hass_ws_client: WebSocketGenerator) -> None:
|
||||||
"""Test WS API."""
|
"""Test WS API."""
|
||||||
assert await async_setup_component(hass, "search", {})
|
assert await async_setup_component(hass, "search", {})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user