State condition can also accept an input_* Entity ID as state value (#39691)

pull/39703/head
Franck Nijhof 2020-09-07 00:36:01 +02:00 committed by GitHub
parent 165dd351b7
commit 1ec3446c56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 103 additions and 4 deletions

View File

@ -4,6 +4,7 @@ from collections import deque
from datetime import datetime, timedelta
import functools as ft
import logging
import re
import sys
from typing import Any, Callable, Container, List, Optional, Set, Union, cast
@ -48,6 +49,10 @@ ASYNC_FROM_CONFIG_FORMAT = "async_{}_from_config"
_LOGGER = logging.getLogger(__name__)
INPUT_ENTITY_ID = re.compile(
r"^input_(?:select|text|number|boolean|datetime)\.(?!.+__)(?!_)[\da-z_]+(?<!_)$"
)
ConditionCheckerType = Callable[[HomeAssistant, TemplateVarsType], bool]
@ -308,13 +313,25 @@ def state(
assert isinstance(entity, State)
if attribute is None:
value = entity.state
else:
value = str(entity.attributes.get(attribute))
if isinstance(req_state, str):
req_state = [req_state]
if attribute is None:
is_state = entity.state in req_state
else:
is_state = str(entity.attributes.get(attribute)) in req_state
is_state = False
for req_state_value in req_state:
state_value = req_state_value
if INPUT_ENTITY_ID.match(req_state_value) is not None:
state_entity = hass.states.get(req_state_value)
if not state_entity:
continue
state_value = state_entity.state
is_state = value == state_value
if is_state:
break
if for_period is None or not is_state:
return is_state

View File

@ -443,6 +443,88 @@ async def test_state_attribute(hass):
assert not test(hass)
async def test_state_using_input_entities(hass):
"""Test state conditions using input_* entities."""
await async_setup_component(
hass,
"input_text",
{
"input_text": {
"hello": {"initial": "goodbye"},
}
},
)
await async_setup_component(
hass,
"input_select",
{
"input_select": {
"hello": {"options": ["cya", "goodbye", "welcome"], "initial": "cya"},
}
},
)
test = await condition.async_from_config(
hass,
{
"condition": "and",
"conditions": [
{
"condition": "state",
"entity_id": "sensor.salut",
"state": [
"input_text.hello",
"input_select.hello",
"input_number.not_exist",
"salut",
],
},
],
},
)
hass.states.async_set("sensor.salut", "goodbye")
assert test(hass)
hass.states.async_set("sensor.salut", "salut")
assert test(hass)
hass.states.async_set("sensor.salut", "hello")
assert not test(hass)
await hass.services.async_call(
"input_text",
"set_value",
{
"entity_id": "input_text.hello",
"value": "hi",
},
blocking=True,
)
assert not test(hass)
hass.states.async_set("sensor.salut", "hi")
assert test(hass)
hass.states.async_set("sensor.salut", "cya")
assert test(hass)
await hass.services.async_call(
"input_select",
"select_option",
{
"entity_id": "input_select.hello",
"option": "welcome",
},
blocking=True,
)
assert not test(hass)
hass.states.async_set("sensor.salut", "welcome")
assert test(hass)
async def test_numeric_state_multiple_entities(hass):
"""Test with multiple entities in condition."""
test = await condition.async_from_config(