Add 'for' to vacuum device triggers (#48506)

* Add 'for' to vacuum device triggers

* Apply suggestions from code review

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Update test_device_trigger.py

* Update test_device_trigger.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
pull/48512/head
Erik Montnemery 2021-03-30 16:40:08 +02:00 committed by GitHub
parent f91de1c8b9
commit 225d79c216
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 0 deletions

View File

@ -10,6 +10,7 @@ from homeassistant.const import (
CONF_DEVICE_ID, CONF_DEVICE_ID,
CONF_DOMAIN, CONF_DOMAIN,
CONF_ENTITY_ID, CONF_ENTITY_ID,
CONF_FOR,
CONF_PLATFORM, CONF_PLATFORM,
CONF_TYPE, CONF_TYPE,
) )
@ -25,6 +26,7 @@ TRIGGER_SCHEMA = TRIGGER_BASE_SCHEMA.extend(
{ {
vol.Required(CONF_ENTITY_ID): cv.entity_id, vol.Required(CONF_ENTITY_ID): cv.entity_id,
vol.Required(CONF_TYPE): vol.In(TRIGGER_TYPES), vol.Required(CONF_TYPE): vol.In(TRIGGER_TYPES),
vol.Optional(CONF_FOR): cv.positive_time_period_dict,
} }
) )
@ -53,6 +55,15 @@ async def async_get_triggers(hass: HomeAssistant, device_id: str) -> list[dict]:
return triggers return triggers
async def async_get_trigger_capabilities(hass: HomeAssistant, config: dict) -> dict:
"""List trigger capabilities."""
return {
"extra_fields": vol.Schema(
{vol.Optional(CONF_FOR): cv.positive_time_period_dict}
)
}
async def async_attach_trigger( async def async_attach_trigger(
hass: HomeAssistant, hass: HomeAssistant,
config: ConfigType, config: ConfigType,
@ -70,6 +81,8 @@ async def async_attach_trigger(
CONF_ENTITY_ID: config[CONF_ENTITY_ID], CONF_ENTITY_ID: config[CONF_ENTITY_ID],
state_trigger.CONF_TO: to_state, state_trigger.CONF_TO: to_state,
} }
if CONF_FOR in config:
state_config[CONF_FOR] = config[CONF_FOR]
state_config = state_trigger.TRIGGER_SCHEMA(state_config) state_config = state_trigger.TRIGGER_SCHEMA(state_config)
return await state_trigger.async_attach_trigger( return await state_trigger.async_attach_trigger(
hass, state_config, action, automation_info, platform_type="device" hass, state_config, action, automation_info, platform_type="device"

View File

@ -1,14 +1,19 @@
"""The tests for Vacuum device triggers.""" """The tests for Vacuum device triggers."""
from datetime import timedelta
import pytest import pytest
import homeassistant.components.automation as automation import homeassistant.components.automation as automation
from homeassistant.components.vacuum import DOMAIN, STATE_CLEANING, STATE_DOCKED from homeassistant.components.vacuum import DOMAIN, STATE_CLEANING, STATE_DOCKED
from homeassistant.helpers import device_registry from homeassistant.helpers import device_registry
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util
from tests.common import ( from tests.common import (
MockConfigEntry, MockConfigEntry,
assert_lists_same, assert_lists_same,
async_fire_time_changed,
async_get_device_automation_capabilities,
async_get_device_automations, async_get_device_automations,
async_mock_service, async_mock_service,
mock_device_registry, mock_device_registry,
@ -64,6 +69,29 @@ async def test_get_triggers(hass, device_reg, entity_reg):
assert_lists_same(triggers, expected_triggers) assert_lists_same(triggers, expected_triggers)
async def test_get_trigger_capabilities(hass, device_reg, entity_reg):
"""Test we get the expected capabilities from a vacuum device."""
config_entry = MockConfigEntry(domain="test", data={})
config_entry.add_to_hass(hass)
device_entry = device_reg.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
)
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
triggers = await async_get_device_automations(hass, "trigger", device_entry.id)
assert len(triggers) == 2
for trigger in triggers:
capabilities = await async_get_device_automation_capabilities(
hass, "trigger", trigger
)
assert capabilities == {
"extra_fields": [
{"name": "for", "optional": True, "type": "positive_time_period_dict"}
]
}
async def test_if_fires_on_state_change(hass, calls): async def test_if_fires_on_state_change(hass, calls):
"""Test for turn_on and turn_off triggers firing.""" """Test for turn_on and turn_off triggers firing."""
hass.states.async_set("vacuum.entity", STATE_DOCKED) hass.states.async_set("vacuum.entity", STATE_DOCKED)
@ -130,3 +158,58 @@ async def test_if_fires_on_state_change(hass, calls):
assert ( assert (
calls[1].data["some"] == "docked - device - vacuum.entity - cleaning - docked" calls[1].data["some"] == "docked - device - vacuum.entity - cleaning - docked"
) )
async def test_if_fires_on_state_change_with_for(hass, calls):
"""Test for triggers firing with delay."""
entity_id = f"{DOMAIN}.entity"
hass.states.async_set(entity_id, STATE_DOCKED)
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "device",
"domain": DOMAIN,
"device_id": "",
"entity_id": entity_id,
"type": "cleaning",
"for": {"seconds": 5},
},
"action": {
"service": "test.automation",
"data_template": {
"some": "turn_off {{ trigger.%s }}"
% "}} - {{ trigger.".join(
(
"platform",
"entity_id",
"from_state.state",
"to_state.state",
"for",
)
)
},
},
}
]
},
)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == STATE_DOCKED
assert len(calls) == 0
hass.states.async_set(entity_id, STATE_CLEANING)
await hass.async_block_till_done()
assert len(calls) == 0
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=10))
await hass.async_block_till_done()
assert len(calls) == 1
await hass.async_block_till_done()
assert (
calls[0].data["some"]
== f"turn_off device - {entity_id} - docked - cleaning - 0:00:05"
)