Search for areas, devices and entities in script choose actions (#57554)

This commit is contained in:
Erik Montnemery 2021-10-12 17:49:07 +02:00 committed by GitHub
parent 8ec38ef034
commit 007af4a7aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 123 additions and 19 deletions

View file

@ -1063,9 +1063,13 @@ class Script:
if self._referenced_areas is not None: if self._referenced_areas is not None:
return self._referenced_areas return self._referenced_areas
referenced: set[str] = set() self._referenced_areas: set[str] = set()
Script._find_referenced_areas(self._referenced_areas, self.sequence)
return self._referenced_areas
for step in self.sequence: @staticmethod
def _find_referenced_areas(referenced, sequence):
for step in sequence:
action = cv.determine_script_action(step) action = cv.determine_script_action(step)
if action == cv.SCRIPT_ACTION_CALL_SERVICE: if action == cv.SCRIPT_ACTION_CALL_SERVICE:
@ -1076,8 +1080,11 @@ class Script:
): ):
_referenced_extract_ids(data, ATTR_AREA_ID, referenced) _referenced_extract_ids(data, ATTR_AREA_ID, referenced)
self._referenced_areas = referenced elif action == cv.SCRIPT_ACTION_CHOOSE:
return referenced for choice in step[CONF_CHOOSE]:
Script._find_referenced_areas(referenced, choice[CONF_SEQUENCE])
if CONF_DEFAULT in step:
Script._find_referenced_areas(referenced, step[CONF_DEFAULT])
@property @property
def referenced_devices(self): def referenced_devices(self):
@ -1085,9 +1092,13 @@ class Script:
if self._referenced_devices is not None: if self._referenced_devices is not None:
return self._referenced_devices return self._referenced_devices
referenced: set[str] = set() self._referenced_devices: set[str] = set()
Script._find_referenced_devices(self._referenced_devices, self.sequence)
return self._referenced_devices
for step in self.sequence: @staticmethod
def _find_referenced_devices(referenced, sequence):
for step in sequence:
action = cv.determine_script_action(step) action = cv.determine_script_action(step)
if action == cv.SCRIPT_ACTION_CALL_SERVICE: if action == cv.SCRIPT_ACTION_CALL_SERVICE:
@ -1104,8 +1115,13 @@ class Script:
elif action == cv.SCRIPT_ACTION_DEVICE_AUTOMATION: elif action == cv.SCRIPT_ACTION_DEVICE_AUTOMATION:
referenced.add(step[CONF_DEVICE_ID]) referenced.add(step[CONF_DEVICE_ID])
self._referenced_devices = referenced elif action == cv.SCRIPT_ACTION_CHOOSE:
return referenced for choice in step[CONF_CHOOSE]:
for cond in choice[CONF_CONDITIONS]:
referenced |= condition.async_extract_devices(cond)
Script._find_referenced_devices(referenced, choice[CONF_SEQUENCE])
if CONF_DEFAULT in step:
Script._find_referenced_devices(referenced, step[CONF_DEFAULT])
@property @property
def referenced_entities(self): def referenced_entities(self):
@ -1113,9 +1129,13 @@ class Script:
if self._referenced_entities is not None: if self._referenced_entities is not None:
return self._referenced_entities return self._referenced_entities
referenced: set[str] = set() self._referenced_entities: set[str] = set()
Script._find_referenced_entities(self._referenced_entities, self.sequence)
return self._referenced_entities
for step in self.sequence: @staticmethod
def _find_referenced_entities(referenced, sequence):
for step in sequence:
action = cv.determine_script_action(step) action = cv.determine_script_action(step)
if action == cv.SCRIPT_ACTION_CALL_SERVICE: if action == cv.SCRIPT_ACTION_CALL_SERVICE:
@ -1133,8 +1153,14 @@ class Script:
elif action == cv.SCRIPT_ACTION_ACTIVATE_SCENE: elif action == cv.SCRIPT_ACTION_ACTIVATE_SCENE:
referenced.add(step[CONF_SCENE]) referenced.add(step[CONF_SCENE])
self._referenced_entities = referenced elif action == cv.SCRIPT_ACTION_CHOOSE:
return referenced for choice in step[CONF_CHOOSE]:
for cond in choice[CONF_CONDITIONS]:
_LOGGER.error("Extracting entities from: %s", cond)
referenced |= condition.async_extract_entities(cond)
Script._find_referenced_entities(referenced, choice[CONF_SEQUENCE])
if CONF_DEFAULT in step:
Script._find_referenced_entities(referenced, step[CONF_DEFAULT])
def run( def run(
self, variables: _VarsType | None = None, context: Context | None = None self, variables: _VarsType | None = None, context: Context | None = None

View file

@ -2282,6 +2282,38 @@ async def test_referenced_entities(hass):
}, },
{"service": "test.script", "data": {"without": "entity_id"}}, {"service": "test.script", "data": {"without": "entity_id"}},
{"scene": "scene.hello"}, {"scene": "scene.hello"},
{
"choose": [
{
"conditions": "{{ states.light.choice_1_cond == 'on' }}",
"sequence": [
{
"service": "test.script",
"data": {"entity_id": "light.choice_1_seq"},
}
],
},
{
"conditions": {
"condition": "state",
"entity_id": "light.choice_2_cond",
"state": "on",
},
"sequence": [
{
"service": "test.script",
"data": {"entity_id": "light.choice_2_seq"},
}
],
},
],
"default": [
{
"service": "test.script",
"data": {"entity_id": "light.default_seq"},
}
],
},
{"event": "test_event"}, {"event": "test_event"},
{"delay": "{{ delay_period }}"}, {"delay": "{{ delay_period }}"},
] ]
@ -2290,13 +2322,18 @@ async def test_referenced_entities(hass):
"test_domain", "test_domain",
) )
assert script_obj.referenced_entities == { assert script_obj.referenced_entities == {
"light.service_not_list", # "light.choice_1_cond", # no entity extraction from template conditions
"light.service_list", "light.choice_1_seq",
"sensor.condition", "light.choice_2_cond",
"scene.hello", "light.choice_2_seq",
"light.default_seq",
"light.direct_entity_referenced", "light.direct_entity_referenced",
"light.entity_in_target",
"light.entity_in_data_template", "light.entity_in_data_template",
"light.entity_in_target",
"light.service_list",
"light.service_not_list",
"scene.hello",
"sensor.condition",
} }
# Test we cache results. # Test we cache results.
assert script_obj.referenced_entities is script_obj.referenced_entities assert script_obj.referenced_entities is script_obj.referenced_entities
@ -2330,19 +2367,60 @@ async def test_referenced_devices(hass):
"service": "test.script", "service": "test.script",
"target": {"device_id": ["target-list-id-1", "target-list-id-2"]}, "target": {"device_id": ["target-list-id-1", "target-list-id-2"]},
}, },
{
"choose": [
{
"conditions": "{{ is_device_attr('choice-2-cond-dev-id', 'model', 'blah') }}",
"sequence": [
{
"service": "test.script",
"target": {
"device_id": "choice-1-seq-device-target"
},
}
],
},
{
"conditions": {
"condition": "device",
"device_id": "choice-2-cond-dev-id",
"domain": "switch",
},
"sequence": [
{
"service": "test.script",
"target": {
"device_id": "choice-2-seq-device-target"
},
}
],
},
],
"default": [
{
"service": "test.script",
"target": {"device_id": "default-device-target"},
}
],
},
] ]
), ),
"Test Name", "Test Name",
"test_domain", "test_domain",
) )
assert script_obj.referenced_devices == { assert script_obj.referenced_devices == {
"script-dev-id", # 'choice-1-cond-dev-id', # no device extraction from template conditions
"choice-1-seq-device-target",
"choice-2-cond-dev-id",
"choice-2-seq-device-target",
"condition-dev-id", "condition-dev-id",
"data-string-id", "data-string-id",
"data-template-string-id", "data-template-string-id",
"target-string-id", "default-device-target",
"script-dev-id",
"target-list-id-1", "target-list-id-1",
"target-list-id-2", "target-list-id-2",
"target-string-id",
} }
# Test we cache results. # Test we cache results.
assert script_obj.referenced_devices is script_obj.referenced_devices assert script_obj.referenced_devices is script_obj.referenced_devices