mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +00:00
Fix delay_on
and delay_off
restarting when a new trigger occurs during the delay (#145050)
This commit is contained in:
parent
0362012bb3
commit
3e0aab55a8
@ -352,6 +352,8 @@ class TriggerBinarySensorEntity(TriggerEntity, BinarySensorEntity, RestoreEntity
|
||||
self._to_render_simple.append(key)
|
||||
self._parse_result.add(key)
|
||||
|
||||
self._last_delay_from: bool | None = None
|
||||
self._last_delay_to: bool | None = None
|
||||
self._delay_cancel: CALLBACK_TYPE | None = None
|
||||
self._auto_off_cancel: CALLBACK_TYPE | None = None
|
||||
self._auto_off_time: datetime | None = None
|
||||
@ -388,6 +390,20 @@ class TriggerBinarySensorEntity(TriggerEntity, BinarySensorEntity, RestoreEntity
|
||||
"""Handle update of the data."""
|
||||
self._process_data()
|
||||
|
||||
raw = self._rendered.get(CONF_STATE)
|
||||
state = template.result_as_boolean(raw)
|
||||
|
||||
key = CONF_DELAY_ON if state else CONF_DELAY_OFF
|
||||
delay = self._rendered.get(key) or self._config.get(key)
|
||||
|
||||
if (
|
||||
self._delay_cancel
|
||||
and delay
|
||||
and self._attr_is_on == self._last_delay_from
|
||||
and state == self._last_delay_to
|
||||
):
|
||||
return
|
||||
|
||||
if self._delay_cancel:
|
||||
self._delay_cancel()
|
||||
self._delay_cancel = None
|
||||
@ -401,12 +417,6 @@ class TriggerBinarySensorEntity(TriggerEntity, BinarySensorEntity, RestoreEntity
|
||||
self.async_write_ha_state()
|
||||
return
|
||||
|
||||
raw = self._rendered.get(CONF_STATE)
|
||||
state = template.result_as_boolean(raw)
|
||||
|
||||
key = CONF_DELAY_ON if state else CONF_DELAY_OFF
|
||||
delay = self._rendered.get(key) or self._config.get(key)
|
||||
|
||||
# state without delay. None means rendering failed.
|
||||
if self._attr_is_on == state or state is None or delay is None:
|
||||
self._set_state(state)
|
||||
@ -422,6 +432,8 @@ class TriggerBinarySensorEntity(TriggerEntity, BinarySensorEntity, RestoreEntity
|
||||
return
|
||||
|
||||
# state with delay. Cancelled if new trigger received
|
||||
self._last_delay_from = self._attr_is_on
|
||||
self._last_delay_to = state
|
||||
self._delay_cancel = async_call_later(
|
||||
self.hass, delay.total_seconds(), partial(self._set_state, state)
|
||||
)
|
||||
|
@ -1225,6 +1225,62 @@ async def test_template_with_trigger_templated_delay_on(hass: HomeAssistant) ->
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("count", "domain"), [(1, "template")])
|
||||
@pytest.mark.parametrize(
|
||||
("config", "delay_state"),
|
||||
[
|
||||
(
|
||||
{
|
||||
"template": {
|
||||
"trigger": {"platform": "event", "event_type": "test_event"},
|
||||
"binary_sensor": {
|
||||
"name": "test",
|
||||
"state": "{{ trigger.event.data.beer == 2 }}",
|
||||
"device_class": "motion",
|
||||
"delay_on": '{{ ({ "seconds": 10 }) }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
STATE_ON,
|
||||
),
|
||||
(
|
||||
{
|
||||
"template": {
|
||||
"trigger": {"platform": "event", "event_type": "test_event"},
|
||||
"binary_sensor": {
|
||||
"name": "test",
|
||||
"state": "{{ trigger.event.data.beer != 2 }}",
|
||||
"device_class": "motion",
|
||||
"delay_off": '{{ ({ "seconds": 10 }) }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
STATE_OFF,
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("start_ha")
|
||||
async def test_trigger_template_delay_with_multiple_triggers(
|
||||
hass: HomeAssistant, delay_state: str
|
||||
) -> None:
|
||||
"""Test trigger based binary sensor with multiple triggers occurring during the delay."""
|
||||
future = dt_util.utcnow()
|
||||
for _ in range(10):
|
||||
# State should still be unknown
|
||||
state = hass.states.get("binary_sensor.test")
|
||||
assert state.state == STATE_UNKNOWN
|
||||
|
||||
hass.bus.async_fire("test_event", {"beer": 2}, context=Context())
|
||||
await hass.async_block_till_done()
|
||||
|
||||
future += timedelta(seconds=1)
|
||||
async_fire_time_changed(hass, future)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get("binary_sensor.test")
|
||||
assert state.state == delay_state
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("count", "domain"), [(1, "template")])
|
||||
@pytest.mark.parametrize(
|
||||
"config",
|
||||
|
Loading…
x
Reference in New Issue
Block a user