diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index ef0b578811e43b..140c233f41e627 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -46,8 +46,7 @@ _RE_NONE_ENTITIES = re.compile(r"distance\(|closest\(", re.I | re.M) _RE_GET_ENTITIES = re.compile( - r"(?:(?:states\.|(?Pis_state|is_state_attr|state_attr|states|expand)" - r"\((?:[\ \'\"]?))(?P[\w]+\.[\w]+)|(?P[\w]+))", + r"(?:(?:(?:states\.|(?Pis_state|is_state_attr|state_attr|states|expand)\((?:[\ \'\"]?))(?P[\w]+\.[\w]+)|states\.(?P[a-z]+)|states\[(?:[\'\"]?)(?P[\w]+))|(?P[\w]+))", re.I | re.M, ) _RE_JINJA_DELIMITERS = re.compile(r"\{%|\{\{") @@ -105,6 +104,12 @@ def extract_entities( extraction_final.append(entity.entity_id) extraction_final.append(result.group("entity_id")) + elif result.group("domain_inner") or result.group("domain_outer"): + extraction_final.extend( + hass.states.async_entity_ids( + result.group("domain_inner") or result.group("domain_outer") + ) + ) if ( variables diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index 89486129760439..fa650b280c602d 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -1812,6 +1812,53 @@ def test_extract_entities_with_variables(hass): ) +def test_extract_entities_domain_states_inner(hass): + """Test extract entities function by domain.""" + hass.states.async_set("light.switch", "on") + hass.states.async_set("light.switch2", "on") + hass.states.async_set("light.switch3", "off") + + assert set( + template.extract_entities( + hass, + "{{ states['light'] | selectattr('state','eq','on') | list | count > 0 }}", + {}, + ) + ) == {"light.switch", "light.switch2", "light.switch3"} + + +def test_extract_entities_domain_states_outer(hass): + """Test extract entities function by domain.""" + hass.states.async_set("light.switch", "on") + hass.states.async_set("light.switch2", "on") + hass.states.async_set("light.switch3", "off") + + assert set( + template.extract_entities( + hass, + "{{ states.light | selectattr('state','eq','off') | list | count > 0 }}", + {}, + ) + ) == {"light.switch", "light.switch2", "light.switch3"} + + +def test_extract_entities_domain_states_outer_with_group(hass): + """Test extract entities function by domain.""" + hass.states.async_set("light.switch", "on") + hass.states.async_set("light.switch2", "on") + hass.states.async_set("light.switch3", "off") + hass.states.async_set("switch.pool_light", "off") + hass.states.async_set("group.lights", "off", {"entity_id": ["switch.pool_light"]}) + + assert set( + template.extract_entities( + hass, + "{{ states.light | selectattr('entity_id', 'in', state_attr('group.lights', 'entity_id')) }}", + {}, + ) + ) == {"light.switch", "light.switch2", "light.switch3", "group.lights"} + + def test_jinja_namespace(hass): """Test Jinja's namespace command can be used.""" test_template = template.Template(