mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Allow any entity to match state condition (#69763)
This commit is contained in:
parent
85f698f873
commit
7087020283
@ -61,6 +61,7 @@ MATCH_ALL: Final = "*"
|
||||
# Entity target all constant
|
||||
ENTITY_MATCH_NONE: Final = "none"
|
||||
ENTITY_MATCH_ALL: Final = "all"
|
||||
ENTITY_MATCH_ANY: Final = "any"
|
||||
|
||||
# If no name is specified
|
||||
DEVICE_DEFAULT_NAME: Final = "Unnamed Device"
|
||||
@ -172,6 +173,7 @@ CONF_LIGHTS: Final = "lights"
|
||||
CONF_LOCATION: Final = "location"
|
||||
CONF_LONGITUDE: Final = "longitude"
|
||||
CONF_MAC: Final = "mac"
|
||||
CONF_MATCH: Final = "match"
|
||||
CONF_MAXIMUM: Final = "maximum"
|
||||
CONF_MEDIA_DIRS: Final = "media_dirs"
|
||||
CONF_METHOD: Final = "method"
|
||||
|
@ -29,10 +29,13 @@ from homeassistant.const import (
|
||||
CONF_DEVICE_ID,
|
||||
CONF_ENTITY_ID,
|
||||
CONF_ID,
|
||||
CONF_MATCH,
|
||||
CONF_STATE,
|
||||
CONF_VALUE_TEMPLATE,
|
||||
CONF_WEEKDAY,
|
||||
CONF_ZONE,
|
||||
ENTITY_MATCH_ALL,
|
||||
ENTITY_MATCH_ANY,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
SUN_EVENT_SUNRISE,
|
||||
@ -524,6 +527,7 @@ def state_from_config(config: ConfigType) -> ConditionCheckerType:
|
||||
req_states: str | list[str] = config.get(CONF_STATE, [])
|
||||
for_period = config.get("for")
|
||||
attribute = config.get(CONF_ATTRIBUTE)
|
||||
match = config.get(CONF_MATCH, ENTITY_MATCH_ALL)
|
||||
|
||||
if not isinstance(req_states, list):
|
||||
req_states = [req_states]
|
||||
@ -532,10 +536,13 @@ def state_from_config(config: ConfigType) -> ConditionCheckerType:
|
||||
def if_state(hass: HomeAssistant, variables: TemplateVarsType = None) -> bool:
|
||||
"""Test if condition."""
|
||||
errors = []
|
||||
result: bool = match != ENTITY_MATCH_ANY
|
||||
for index, entity_id in enumerate(entity_ids):
|
||||
try:
|
||||
with trace_path(["entity_id", str(index)]), trace_condition(variables):
|
||||
if not state(hass, entity_id, req_states, for_period, attribute):
|
||||
if state(hass, entity_id, req_states, for_period, attribute):
|
||||
result = True
|
||||
elif match == ENTITY_MATCH_ALL:
|
||||
return False
|
||||
except ConditionError as ex:
|
||||
errors.append(
|
||||
@ -548,7 +555,7 @@ def state_from_config(config: ConfigType) -> ConditionCheckerType:
|
||||
if errors:
|
||||
raise ConditionErrorContainer("state", errors=errors)
|
||||
|
||||
return True
|
||||
return result
|
||||
|
||||
return if_state
|
||||
|
||||
|
@ -49,6 +49,7 @@ from homeassistant.const import (
|
||||
CONF_EVENT_DATA_TEMPLATE,
|
||||
CONF_FOR,
|
||||
CONF_ID,
|
||||
CONF_MATCH,
|
||||
CONF_PLATFORM,
|
||||
CONF_REPEAT,
|
||||
CONF_SCAN_INTERVAL,
|
||||
@ -68,6 +69,7 @@ from homeassistant.const import (
|
||||
CONF_WAIT_TEMPLATE,
|
||||
CONF_WHILE,
|
||||
ENTITY_MATCH_ALL,
|
||||
ENTITY_MATCH_ANY,
|
||||
ENTITY_MATCH_NONE,
|
||||
SUN_EVENT_SUNRISE,
|
||||
SUN_EVENT_SUNSET,
|
||||
@ -1105,6 +1107,9 @@ STATE_CONDITION_BASE_SCHEMA = {
|
||||
**CONDITION_BASE_SCHEMA,
|
||||
vol.Required(CONF_CONDITION): "state",
|
||||
vol.Required(CONF_ENTITY_ID): entity_ids_or_uuids,
|
||||
vol.Optional(CONF_MATCH, default=ENTITY_MATCH_ALL): vol.All(
|
||||
vol.Lower, vol.Any(ENTITY_MATCH_ALL, ENTITY_MATCH_ANY)
|
||||
),
|
||||
vol.Optional(CONF_ATTRIBUTE): str,
|
||||
vol.Optional(CONF_FOR): positive_time_period,
|
||||
# To support use_trigger_value in automation
|
||||
|
@ -15,6 +15,7 @@ from homeassistant.const import (
|
||||
SUN_EVENT_SUNRISE,
|
||||
SUN_EVENT_SUNSET,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConditionError, HomeAssistantError
|
||||
from homeassistant.helpers import (
|
||||
condition,
|
||||
@ -1020,6 +1021,40 @@ async def test_state_multiple_entities(hass):
|
||||
assert not test(hass)
|
||||
|
||||
|
||||
async def test_state_multiple_entities_match_any(hass: HomeAssistant) -> None:
|
||||
"""Test with multiple entities in condition with match any."""
|
||||
config = {
|
||||
"condition": "and",
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "state",
|
||||
"entity_id": ["sensor.temperature_1", "sensor.temperature_2"],
|
||||
"match": "any",
|
||||
"state": "100",
|
||||
},
|
||||
],
|
||||
}
|
||||
config = cv.CONDITION_SCHEMA(config)
|
||||
config = await condition.async_validate_condition_config(hass, config)
|
||||
test = await condition.async_from_config(hass, config)
|
||||
|
||||
hass.states.async_set("sensor.temperature_1", 100)
|
||||
hass.states.async_set("sensor.temperature_2", 100)
|
||||
assert test(hass)
|
||||
|
||||
hass.states.async_set("sensor.temperature_1", 101)
|
||||
hass.states.async_set("sensor.temperature_2", 100)
|
||||
assert test(hass)
|
||||
|
||||
hass.states.async_set("sensor.temperature_1", 100)
|
||||
hass.states.async_set("sensor.temperature_2", 101)
|
||||
assert test(hass)
|
||||
|
||||
hass.states.async_set("sensor.temperature_1", 101)
|
||||
hass.states.async_set("sensor.temperature_2", 101)
|
||||
assert not test(hass)
|
||||
|
||||
|
||||
async def test_multiple_states(hass):
|
||||
"""Test with multiple states in condition."""
|
||||
config = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user