Fix time trigger based on entities ignoring entities if initially in the past (#43431)

This commit is contained in:
Paulus Schoutsen 2020-11-20 15:43:28 +01:00 committed by GitHub
parent 82b7cc8ac7
commit bbb82ded68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 3 deletions

View File

@ -143,9 +143,12 @@ async def async_attach_trigger(hass, config, action, automation_info):
if remove: if remove:
entities[entity_id] = remove entities[entity_id] = remove
to_track = []
for at_time in config[CONF_AT]: for at_time in config[CONF_AT]:
if isinstance(at_time, str): if isinstance(at_time, str):
# entity # entity
to_track.append(at_time)
update_entity_trigger(at_time, new_state=hass.states.get(at_time)) update_entity_trigger(at_time, new_state=hass.states.get(at_time))
else: else:
# datetime.time # datetime.time
@ -161,9 +164,7 @@ async def async_attach_trigger(hass, config, action, automation_info):
# Track state changes of any entities. # Track state changes of any entities.
removes.append( removes.append(
async_track_state_change_event( async_track_state_change_event(hass, to_track, update_entity_trigger_event)
hass, list(entities), update_entity_trigger_event
)
) )
@callback @callback

View File

@ -2,8 +2,10 @@
from datetime import timedelta from datetime import timedelta
import pytest import pytest
import voluptuous as vol
from homeassistant.components import automation, sensor from homeassistant.components import automation, sensor
from homeassistant.components.homeassistant.triggers import time
from homeassistant.const import ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, SERVICE_TURN_OFF from homeassistant.const import ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, SERVICE_TURN_OFF
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
@ -492,3 +494,93 @@ async def test_if_fires_using_at_sensor(hass, calls):
# We should not have listened to anything # We should not have listened to anything
assert len(calls) == 2 assert len(calls) == 2
@pytest.mark.parametrize(
"conf",
[
{"platform": "time", "at": "input_datetime.bla"},
{"platform": "time", "at": "sensor.bla"},
{"platform": "time", "at": "12:34"},
],
)
def test_schema_valid(conf):
"""Make sure we don't accept number for 'at' value."""
time.TRIGGER_SCHEMA(conf)
@pytest.mark.parametrize(
"conf",
[
{"platform": "time", "at": "binary_sensor.bla"},
{"platform": "time", "at": 745},
{"platform": "time", "at": "25:00"},
],
)
def test_schema_invalid(conf):
"""Make sure we don't accept number for 'at' value."""
with pytest.raises(vol.Invalid):
time.TRIGGER_SCHEMA(conf)
async def test_datetime_in_past_on_load(hass, calls):
"""Test time trigger works if input_datetime is in past."""
await async_setup_component(
hass,
"input_datetime",
{"input_datetime": {"my_trigger": {"has_date": True, "has_time": True}}},
)
now = dt_util.now()
past = now - timedelta(days=2)
future = now + timedelta(days=1)
await hass.services.async_call(
"input_datetime",
"set_datetime",
{
ATTR_ENTITY_ID: "input_datetime.my_trigger",
"datetime": str(past.replace(tzinfo=None)),
},
blocking=True,
)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: {
"trigger": {"platform": "time", "at": "input_datetime.my_trigger"},
"action": {
"service": "test.automation",
"data_template": {
"some": "{{ trigger.platform }}-{{ trigger.now.day }}-{{ trigger.now.hour }}-{{trigger.entity_id}}"
},
},
}
},
)
async_fire_time_changed(hass, now)
await hass.async_block_till_done()
assert len(calls) == 0
await hass.services.async_call(
"input_datetime",
"set_datetime",
{
ATTR_ENTITY_ID: "input_datetime.my_trigger",
"datetime": str(future.replace(tzinfo=None)),
},
blocking=True,
)
async_fire_time_changed(hass, future + timedelta(seconds=1))
await hass.async_block_till_done()
assert len(calls) == 1
assert (
calls[0].data["some"]
== f"time-{future.day}-{future.hour}-input_datetime.my_trigger"
)