Add NOT condition helper (#34624)
This commit is contained in:
parent
6404882ec4
commit
c93c6a66e8
4 changed files with 106 additions and 0 deletions
|
@ -54,6 +54,7 @@ CONF_SKIP_CONDITION = "skip_condition"
|
|||
|
||||
CONDITION_USE_TRIGGER_VALUES = "use_trigger_values"
|
||||
CONDITION_TYPE_AND = "and"
|
||||
CONDITION_TYPE_NOT = "not"
|
||||
CONDITION_TYPE_OR = "or"
|
||||
|
||||
DEFAULT_CONDITION_TYPE = CONDITION_TYPE_AND
|
||||
|
|
|
@ -137,6 +137,32 @@ async def async_or_from_config(
|
|||
return if_or_condition
|
||||
|
||||
|
||||
async def async_not_from_config(
|
||||
hass: HomeAssistant, config: ConfigType, config_validation: bool = True
|
||||
) -> ConditionCheckerType:
|
||||
"""Create multi condition matcher using 'NOT'."""
|
||||
if config_validation:
|
||||
config = cv.NOT_CONDITION_SCHEMA(config)
|
||||
checks = [
|
||||
await async_from_config(hass, entry, False) for entry in config["conditions"]
|
||||
]
|
||||
|
||||
def if_not_condition(
|
||||
hass: HomeAssistant, variables: TemplateVarsType = None
|
||||
) -> bool:
|
||||
"""Test not condition."""
|
||||
try:
|
||||
for check in checks:
|
||||
if check(hass, variables):
|
||||
return False
|
||||
except Exception as ex: # pylint: disable=broad-except
|
||||
_LOGGER.warning("Error during not-condition: %s", ex)
|
||||
|
||||
return True
|
||||
|
||||
return if_not_condition
|
||||
|
||||
|
||||
def numeric_state(
|
||||
hass: HomeAssistant,
|
||||
entity: Union[None, str, State],
|
||||
|
|
|
@ -924,6 +924,17 @@ OR_CONDITION_SCHEMA = vol.Schema(
|
|||
}
|
||||
)
|
||||
|
||||
NOT_CONDITION_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_CONDITION): "not",
|
||||
vol.Required("conditions"): vol.All(
|
||||
ensure_list,
|
||||
# pylint: disable=unnecessary-lambda
|
||||
[lambda value: CONDITION_SCHEMA(value)],
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
DEVICE_CONDITION_BASE_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_CONDITION): "device",
|
||||
|
@ -945,6 +956,7 @@ CONDITION_SCHEMA: vol.Schema = key_value_schemas(
|
|||
"zone": ZONE_CONDITION_SCHEMA,
|
||||
"and": AND_CONDITION_SCHEMA,
|
||||
"or": OR_CONDITION_SCHEMA,
|
||||
"not": NOT_CONDITION_SCHEMA,
|
||||
"device": DEVICE_CONDITION_SCHEMA,
|
||||
},
|
||||
)
|
||||
|
|
|
@ -127,6 +127,73 @@ async def test_or_condition_with_template(hass):
|
|||
assert test(hass)
|
||||
|
||||
|
||||
async def test_not_condition(hass):
|
||||
"""Test the 'not' condition."""
|
||||
test = await condition.async_from_config(
|
||||
hass,
|
||||
{
|
||||
"condition": "not",
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "state",
|
||||
"entity_id": "sensor.temperature",
|
||||
"state": "100",
|
||||
},
|
||||
{
|
||||
"condition": "numeric_state",
|
||||
"entity_id": "sensor.temperature",
|
||||
"below": 50,
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
hass.states.async_set("sensor.temperature", 101)
|
||||
assert test(hass)
|
||||
|
||||
hass.states.async_set("sensor.temperature", 50)
|
||||
assert test(hass)
|
||||
|
||||
hass.states.async_set("sensor.temperature", 49)
|
||||
assert not test(hass)
|
||||
|
||||
hass.states.async_set("sensor.temperature", 100)
|
||||
assert not test(hass)
|
||||
|
||||
|
||||
async def test_not_condition_with_template(hass):
|
||||
"""Test the 'or' condition."""
|
||||
test = await condition.async_from_config(
|
||||
hass,
|
||||
{
|
||||
"condition": "not",
|
||||
"conditions": [
|
||||
{
|
||||
"condition": "template",
|
||||
"value_template": '{{ states.sensor.temperature.state == "100" }}',
|
||||
},
|
||||
{
|
||||
"condition": "numeric_state",
|
||||
"entity_id": "sensor.temperature",
|
||||
"below": 50,
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
hass.states.async_set("sensor.temperature", 101)
|
||||
assert test(hass)
|
||||
|
||||
hass.states.async_set("sensor.temperature", 50)
|
||||
assert test(hass)
|
||||
|
||||
hass.states.async_set("sensor.temperature", 49)
|
||||
assert not test(hass)
|
||||
|
||||
hass.states.async_set("sensor.temperature", 100)
|
||||
assert not test(hass)
|
||||
|
||||
|
||||
async def test_time_window(hass):
|
||||
"""Test time condition windows."""
|
||||
sixam = dt.parse_time("06:00:00")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue