mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Add support for multiple time triggers in automations (#37975)
* Add support for multiple time triggers in automations * Attach with single callback * Patch time in tests * Improve test coverage * Adjusting my facepalm moment
This commit is contained in:
parent
99b624a676
commit
fa9866db96
@ -13,20 +13,37 @@ from homeassistant.helpers.event import async_track_time_change
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
TRIGGER_SCHEMA = vol.Schema(
|
TRIGGER_SCHEMA = vol.Schema(
|
||||||
{vol.Required(CONF_PLATFORM): "time", vol.Required(CONF_AT): cv.time}
|
{
|
||||||
|
vol.Required(CONF_PLATFORM): "time",
|
||||||
|
vol.Required(CONF_AT): vol.All(cv.ensure_list, [cv.time]),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_attach_trigger(hass, config, action, automation_info):
|
async def async_attach_trigger(hass, config, action, automation_info):
|
||||||
"""Listen for state changes based on configuration."""
|
"""Listen for state changes based on configuration."""
|
||||||
at_time = config.get(CONF_AT)
|
at_times = config[CONF_AT]
|
||||||
hours, minutes, seconds = at_time.hour, at_time.minute, at_time.second
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def time_automation_listener(now):
|
def time_automation_listener(now):
|
||||||
"""Listen for time changes and calls action."""
|
"""Listen for time changes and calls action."""
|
||||||
hass.async_run_job(action, {"trigger": {"platform": "time", "now": now}})
|
hass.async_run_job(action, {"trigger": {"platform": "time", "now": now}})
|
||||||
|
|
||||||
return async_track_time_change(
|
removes = [
|
||||||
hass, time_automation_listener, hour=hours, minute=minutes, second=seconds
|
async_track_time_change(
|
||||||
)
|
hass,
|
||||||
|
time_automation_listener,
|
||||||
|
hour=at_time.hour,
|
||||||
|
minute=at_time.minute,
|
||||||
|
second=at_time.second,
|
||||||
|
)
|
||||||
|
for at_time in at_times
|
||||||
|
]
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def remove_track_time_changes():
|
||||||
|
"""Remove tracked time changes."""
|
||||||
|
for remove in removes:
|
||||||
|
remove()
|
||||||
|
|
||||||
|
return remove_track_time_changes
|
||||||
|
@ -4,10 +4,11 @@ from datetime import timedelta
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import homeassistant.components.automation as automation
|
import homeassistant.components.automation as automation
|
||||||
|
from homeassistant.const import 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
|
||||||
|
|
||||||
from tests.async_mock import patch
|
from tests.async_mock import Mock, patch
|
||||||
from tests.common import (
|
from tests.common import (
|
||||||
assert_setup_component,
|
assert_setup_component,
|
||||||
async_fire_time_changed,
|
async_fire_time_changed,
|
||||||
@ -66,6 +67,53 @@ async def test_if_fires_using_at(hass, calls):
|
|||||||
assert calls[0].data["some"] == "time - 5"
|
assert calls[0].data["some"] == "time - 5"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_if_fires_using_multiple_at(hass, calls):
|
||||||
|
"""Test for firing at."""
|
||||||
|
|
||||||
|
now = dt_util.utcnow()
|
||||||
|
|
||||||
|
time_that_will_not_match_right_away = now.replace(
|
||||||
|
year=now.year + 1, hour=4, minute=59, second=0
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.util.dt.utcnow", return_value=time_that_will_not_match_right_away
|
||||||
|
):
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
automation.DOMAIN,
|
||||||
|
{
|
||||||
|
automation.DOMAIN: {
|
||||||
|
"trigger": {"platform": "time", "at": ["5:00:00", "6:00:00"]},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data_template": {
|
||||||
|
"some": "{{ trigger.platform }} - {{ trigger.now.hour }}"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
now = dt_util.utcnow()
|
||||||
|
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, now.replace(year=now.year + 1, hour=5, minute=0, second=0)
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(calls) == 1
|
||||||
|
assert calls[0].data["some"] == "time - 5"
|
||||||
|
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, now.replace(year=now.year + 1, hour=6, minute=0, second=0)
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(calls) == 2
|
||||||
|
assert calls[1].data["some"] == "time - 6"
|
||||||
|
|
||||||
|
|
||||||
async def test_if_not_fires_using_wrong_at(hass, calls):
|
async def test_if_not_fires_using_wrong_at(hass, calls):
|
||||||
"""YAML translates time values to total seconds.
|
"""YAML translates time values to total seconds.
|
||||||
|
|
||||||
@ -231,3 +279,35 @@ async def test_if_action_list_weekday(hass, calls):
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert len(calls) == 2
|
assert len(calls) == 2
|
||||||
|
|
||||||
|
|
||||||
|
async def test_untrack_time_change(hass):
|
||||||
|
"""Test for removing tracked time changes."""
|
||||||
|
mock_track_time_change = Mock()
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.automation.time.async_track_time_change",
|
||||||
|
return_value=mock_track_time_change,
|
||||||
|
):
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
automation.DOMAIN,
|
||||||
|
{
|
||||||
|
automation.DOMAIN: {
|
||||||
|
"alias": "test",
|
||||||
|
"trigger": {
|
||||||
|
"platform": "time",
|
||||||
|
"at": ["5:00:00", "6:00:00", "7:00:00"],
|
||||||
|
},
|
||||||
|
"action": {"service": "test.automation", "data": {"test": "test"}},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
automation.DOMAIN,
|
||||||
|
SERVICE_TURN_OFF,
|
||||||
|
{ATTR_ENTITY_ID: "automation.test"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(mock_track_time_change.mock_calls) == 3
|
||||||
|
Loading…
x
Reference in New Issue
Block a user