Skip to content

Commit

Permalink
Do not trigger when numeric_state is already true
Browse files Browse the repository at this point in the history
  • Loading branch information
amelchio committed Nov 26, 2020
1 parent eb3e5cf commit 21e9328
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 39 deletions.
17 changes: 10 additions & 7 deletions homeassistant/components/bayesian/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,16 @@ def _process_numeric_state(self, entity_observation):
"""Return True if numeric condition is met."""
entity = entity_observation["entity_id"]

return condition.async_numeric_state(
self.hass,
entity,
entity_observation.get("below"),
entity_observation.get("above"),
None,
entity_observation,
return (
condition.async_numeric_state(
self.hass,
entity,
entity_observation.get("below"),
entity_observation.get("above"),
None,
entity_observation,
)
is True
)

def _process_state(self, entity_observation):
Expand Down
7 changes: 5 additions & 2 deletions homeassistant/components/cover/device_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,11 @@ def template_if(hass: HomeAssistant, variables: TemplateVarsType = None) -> bool
"""Validate template based if-condition."""
value_template.hass = hass

return condition.async_numeric_state(
hass, config[ATTR_ENTITY_ID], max_pos, min_pos, value_template
return (
condition.async_numeric_state(
hass, config[ATTR_ENTITY_ID], max_pos, min_pos, value_template
)
is True
)

return template_if
21 changes: 12 additions & 9 deletions homeassistant/components/homeassistant/triggers/numeric_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ async def async_attach_trigger(
template.attach(hass, time_delta)
value_template = config.get(CONF_VALUE_TEMPLATE)
unsub_track_same = {}
entities_triggered = set()
period: dict = {}
attribute = config.get(CONF_ATTRIBUTE)
job = HassJob(action)
Expand All @@ -93,13 +92,18 @@ def variables(entity_id):
@callback
def check_numeric_state(entity_id, from_s, to_s):
"""Return True if criteria are now met."""
if to_s is None:
return False

return condition.async_numeric_state(
hass, to_s, below, above, value_template, variables(entity_id), attribute
)

# Armed entities are ready to fire because the condition has been False.
# Unknown and unavailable entities (condition is None) do not arm.
armed_entities = {
entity_id
for entity_id in entity_ids
if check_numeric_state(entity_id, None, entity_id) is False
}

@callback
def state_automation_listener(event):
"""Listen for state changes and calls action."""
Expand Down Expand Up @@ -129,10 +133,10 @@ def call_action():

matching = check_numeric_state(entity_id, from_s, to_s)

if not matching:
entities_triggered.discard(entity_id)
elif entity_id not in entities_triggered:
entities_triggered.add(entity_id)
if matching is False:
armed_entities.add(entity_id)
elif matching is True and entity_id in armed_entities:
armed_entities.discard(entity_id)

if time_delta:
try:
Expand All @@ -145,7 +149,6 @@ def call_action():
automation_info["name"],
ex,
)
entities_triggered.discard(entity_id)
return

unsub_track_same[entity_id] = async_track_same_state(
Expand Down
30 changes: 16 additions & 14 deletions homeassistant/helpers/condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def numeric_state(
above: Optional[Union[float, str]] = None,
value_template: Optional[Template] = None,
variables: TemplateVarsType = None,
) -> bool:
) -> Optional[bool]:
"""Test a numeric state condition."""
return run_callback_threadsafe(
hass.loop,
Expand All @@ -202,13 +202,13 @@ def async_numeric_state(
value_template: Optional[Template] = None,
variables: TemplateVarsType = None,
attribute: Optional[str] = None,
) -> bool:
) -> Optional[bool]:
"""Test a numeric state condition."""
if isinstance(entity, str):
entity = hass.states.get(entity)

if entity is None or (attribute is not None and attribute not in entity.attributes):
return False
return None

value: Any = None
if value_template is None:
Expand All @@ -223,10 +223,10 @@ def async_numeric_state(
value = value_template.async_render(variables)
except TemplateError as ex:
_LOGGER.error("Template error: %s", ex)
return False
return None

if value in (STATE_UNAVAILABLE, STATE_UNKNOWN):
return False
return None

try:
fvalue = float(value)
Expand All @@ -236,28 +236,30 @@ def async_numeric_state(
entity,
value,
)
return False
return None

if below is not None:
if isinstance(below, str):
below_entity = hass.states.get(below)
if (
not below_entity
or below_entity.state in (STATE_UNAVAILABLE, STATE_UNKNOWN)
or fvalue >= float(below_entity.state)
if not below_entity or below_entity.state in (
STATE_UNAVAILABLE,
STATE_UNKNOWN,
):
return None
if fvalue >= float(below_entity.state):
return False
elif fvalue >= below:
return False

if above is not None:
if isinstance(above, str):
above_entity = hass.states.get(above)
if (
not above_entity
or above_entity.state in (STATE_UNAVAILABLE, STATE_UNKNOWN)
or fvalue <= float(above_entity.state)
if not above_entity or above_entity.state in (
STATE_UNAVAILABLE,
STATE_UNKNOWN,
):
return None
if fvalue <= float(above_entity.state):
return False
elif fvalue <= above:
return False
Expand Down
Loading

0 comments on commit 21e9328

Please sign in to comment.