mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Add turned on or off device trigger to toggle entity (#61089)
* Add turned on or off device trigger to toggle entity * Renamed changed_states trigger to toggled * Adjust tests * Fix homekit triggers test * Add tests * Adjust tests after rebase Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
8f99cb51b5
commit
e9b746e874
@ -1,4 +1,5 @@
|
|||||||
"""Constants for device automations."""
|
"""Constants for device automations."""
|
||||||
|
CONF_CHANGED_STATES = "toggled"
|
||||||
CONF_IS_OFF = "is_off"
|
CONF_IS_OFF = "is_off"
|
||||||
CONF_IS_ON = "is_on"
|
CONF_IS_ON = "is_on"
|
||||||
CONF_TOGGLE = "toggle"
|
CONF_TOGGLE = "toggle"
|
||||||
|
108
homeassistant/components/device_automation/entity.py
Normal file
108
homeassistant/components/device_automation/entity.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
"""Device automation helpers for entity."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.components.automation import (
|
||||||
|
AutomationActionType,
|
||||||
|
AutomationTriggerInfo,
|
||||||
|
)
|
||||||
|
from homeassistant.components.device_automation.const import CONF_CHANGED_STATES
|
||||||
|
from homeassistant.components.homeassistant.triggers import state as state_trigger
|
||||||
|
from homeassistant.const import CONF_ENTITY_ID, CONF_FOR, CONF_PLATFORM, CONF_TYPE
|
||||||
|
from homeassistant.core import CALLBACK_TYPE, HomeAssistant
|
||||||
|
from homeassistant.helpers import config_validation as cv
|
||||||
|
from homeassistant.helpers.entity_registry import async_entries_for_device
|
||||||
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
|
from . import DEVICE_TRIGGER_BASE_SCHEMA
|
||||||
|
|
||||||
|
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||||
|
|
||||||
|
ENTITY_TRIGGERS = [
|
||||||
|
{
|
||||||
|
# Trigger when entity is turned on or off
|
||||||
|
CONF_PLATFORM: "device",
|
||||||
|
CONF_TYPE: CONF_CHANGED_STATES,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
||||||
|
vol.Required(CONF_TYPE): vol.In([CONF_CHANGED_STATES]),
|
||||||
|
vol.Optional(CONF_FOR): cv.positive_time_period_dict,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_attach_trigger(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config: ConfigType,
|
||||||
|
action: AutomationActionType,
|
||||||
|
automation_info: AutomationTriggerInfo,
|
||||||
|
) -> CALLBACK_TYPE:
|
||||||
|
"""Listen for state changes based on configuration."""
|
||||||
|
to_state = None
|
||||||
|
state_config = {
|
||||||
|
CONF_PLATFORM: "state",
|
||||||
|
state_trigger.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||||
|
state_trigger.CONF_TO: to_state,
|
||||||
|
}
|
||||||
|
if CONF_FOR in config:
|
||||||
|
state_config[CONF_FOR] = config[CONF_FOR]
|
||||||
|
|
||||||
|
state_config = await state_trigger.async_validate_trigger_config(hass, state_config)
|
||||||
|
return await state_trigger.async_attach_trigger(
|
||||||
|
hass, state_config, action, automation_info, platform_type="device"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def _async_get_automations(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
device_id: str,
|
||||||
|
automation_templates: list[dict[str, str]],
|
||||||
|
domain: str,
|
||||||
|
) -> list[dict[str, str]]:
|
||||||
|
"""List device automations."""
|
||||||
|
automations: list[dict[str, str]] = []
|
||||||
|
entity_registry = await hass.helpers.entity_registry.async_get_registry()
|
||||||
|
|
||||||
|
entries = [
|
||||||
|
entry
|
||||||
|
for entry in async_entries_for_device(entity_registry, device_id)
|
||||||
|
if entry.domain == domain
|
||||||
|
]
|
||||||
|
|
||||||
|
for entry in entries:
|
||||||
|
automations.extend(
|
||||||
|
{
|
||||||
|
**template,
|
||||||
|
"device_id": device_id,
|
||||||
|
"entity_id": entry.entity_id,
|
||||||
|
"domain": domain,
|
||||||
|
}
|
||||||
|
for template in automation_templates
|
||||||
|
)
|
||||||
|
|
||||||
|
return automations
|
||||||
|
|
||||||
|
|
||||||
|
async def async_get_triggers(
|
||||||
|
hass: HomeAssistant, device_id: str, domain: str
|
||||||
|
) -> list[dict[str, Any]]:
|
||||||
|
"""List device triggers."""
|
||||||
|
return await _async_get_automations(hass, device_id, ENTITY_TRIGGERS, domain)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_get_trigger_capabilities(
|
||||||
|
hass: HomeAssistant, config: ConfigType
|
||||||
|
) -> dict[str, vol.Schema]:
|
||||||
|
"""List trigger capabilities."""
|
||||||
|
return {
|
||||||
|
"extra_fields": vol.Schema(
|
||||||
|
{vol.Optional(CONF_FOR): cv.positive_time_period_dict}
|
||||||
|
)
|
||||||
|
}
|
@ -23,7 +23,7 @@ from homeassistant.helpers import condition, config_validation as cv
|
|||||||
from homeassistant.helpers.entity_registry import async_entries_for_device
|
from homeassistant.helpers.entity_registry import async_entries_for_device
|
||||||
from homeassistant.helpers.typing import ConfigType, TemplateVarsType
|
from homeassistant.helpers.typing import ConfigType, TemplateVarsType
|
||||||
|
|
||||||
from . import DEVICE_TRIGGER_BASE_SCHEMA
|
from . import DEVICE_TRIGGER_BASE_SCHEMA, entity
|
||||||
from .const import (
|
from .const import (
|
||||||
CONF_IS_OFF,
|
CONF_IS_OFF,
|
||||||
CONF_IS_ON,
|
CONF_IS_ON,
|
||||||
@ -94,7 +94,7 @@ CONDITION_SCHEMA = cv.DEVICE_CONDITION_BASE_SCHEMA.extend(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend(
|
_TOGGLE_TRIGGER_SCHEMA = DEVICE_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([CONF_TURNED_OFF, CONF_TURNED_ON]),
|
vol.Required(CONF_TYPE): vol.In([CONF_TURNED_OFF, CONF_TURNED_ON]),
|
||||||
@ -102,6 +102,8 @@ TRIGGER_SCHEMA = DEVICE_TRIGGER_BASE_SCHEMA.extend(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
TRIGGER_SCHEMA = vol.Any(entity.TRIGGER_SCHEMA, _TOGGLE_TRIGGER_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
async def async_call_action_from_config(
|
async def async_call_action_from_config(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -155,6 +157,9 @@ async def async_attach_trigger(
|
|||||||
automation_info: AutomationTriggerInfo,
|
automation_info: AutomationTriggerInfo,
|
||||||
) -> CALLBACK_TYPE:
|
) -> CALLBACK_TYPE:
|
||||||
"""Listen for state changes based on configuration."""
|
"""Listen for state changes based on configuration."""
|
||||||
|
if config[CONF_TYPE] not in [CONF_TURNED_ON, CONF_TURNED_OFF]:
|
||||||
|
return await entity.async_attach_trigger(hass, config, action, automation_info)
|
||||||
|
|
||||||
if config[CONF_TYPE] == CONF_TURNED_ON:
|
if config[CONF_TYPE] == CONF_TURNED_ON:
|
||||||
to_state = "on"
|
to_state = "on"
|
||||||
else:
|
else:
|
||||||
@ -221,7 +226,11 @@ async def async_get_triggers(
|
|||||||
hass: HomeAssistant, device_id: str, domain: str
|
hass: HomeAssistant, device_id: str, domain: str
|
||||||
) -> list[dict[str, Any]]:
|
) -> list[dict[str, Any]]:
|
||||||
"""List device triggers."""
|
"""List device triggers."""
|
||||||
return await _async_get_automations(hass, device_id, ENTITY_TRIGGERS, domain)
|
triggers = await entity.async_get_triggers(hass, device_id, domain)
|
||||||
|
triggers.extend(
|
||||||
|
await _async_get_automations(hass, device_id, ENTITY_TRIGGERS, domain)
|
||||||
|
)
|
||||||
|
return triggers
|
||||||
|
|
||||||
|
|
||||||
async def async_get_condition_capabilities(
|
async def async_get_condition_capabilities(
|
||||||
@ -239,6 +248,9 @@ async def async_get_trigger_capabilities(
|
|||||||
hass: HomeAssistant, config: ConfigType
|
hass: HomeAssistant, config: ConfigType
|
||||||
) -> dict[str, vol.Schema]:
|
) -> dict[str, vol.Schema]:
|
||||||
"""List trigger capabilities."""
|
"""List trigger capabilities."""
|
||||||
|
if config[CONF_TYPE] not in [CONF_TURNED_ON, CONF_TURNED_OFF]:
|
||||||
|
return await entity.async_get_trigger_capabilities(hass, config)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"extra_fields": vol.Schema(
|
"extra_fields": vol.Schema(
|
||||||
{vol.Optional(CONF_FOR): cv.positive_time_period_dict}
|
{vol.Optional(CONF_FOR): cv.positive_time_period_dict}
|
||||||
|
@ -16,8 +16,9 @@ from homeassistant.helpers.typing import ConfigType
|
|||||||
|
|
||||||
from . import DOMAIN
|
from . import DOMAIN
|
||||||
|
|
||||||
TRIGGER_SCHEMA = toggle_entity.TRIGGER_SCHEMA.extend(
|
TRIGGER_SCHEMA = vol.All(
|
||||||
{vol.Required(CONF_DOMAIN): DOMAIN}
|
toggle_entity.TRIGGER_SCHEMA,
|
||||||
|
vol.Schema({vol.Required(CONF_DOMAIN): DOMAIN}, extra=vol.ALLOW_EXTRA),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"is_off": "{entity_name} is off"
|
"is_off": "{entity_name} is off"
|
||||||
},
|
},
|
||||||
"trigger_type": {
|
"trigger_type": {
|
||||||
|
"toggled": "{entity_name} turned on or off",
|
||||||
"turned_on": "{entity_name} turned on",
|
"turned_on": "{entity_name} turned on",
|
||||||
"turned_off": "{entity_name} turned off"
|
"turned_off": "{entity_name} turned off"
|
||||||
},
|
},
|
||||||
|
@ -35,7 +35,7 @@ from . import DOMAIN
|
|||||||
|
|
||||||
# mypy: disallow-any-generics
|
# mypy: disallow-any-generics
|
||||||
|
|
||||||
TARGET_TRIGGER_SCHEMA = vol.All(
|
HUMIDIFIER_TRIGGER_SCHEMA = vol.All(
|
||||||
DEVICE_TRIGGER_BASE_SCHEMA.extend(
|
DEVICE_TRIGGER_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
||||||
@ -48,12 +48,14 @@ TARGET_TRIGGER_SCHEMA = vol.All(
|
|||||||
cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE),
|
cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE),
|
||||||
)
|
)
|
||||||
|
|
||||||
TOGGLE_TRIGGER_SCHEMA = toggle_entity.TRIGGER_SCHEMA.extend(
|
TRIGGER_SCHEMA = vol.All(
|
||||||
{vol.Required(CONF_DOMAIN): DOMAIN}
|
vol.Any(
|
||||||
|
HUMIDIFIER_TRIGGER_SCHEMA,
|
||||||
|
toggle_entity.TRIGGER_SCHEMA,
|
||||||
|
),
|
||||||
|
vol.Schema({vol.Required(CONF_DOMAIN): DOMAIN}, extra=vol.ALLOW_EXTRA),
|
||||||
)
|
)
|
||||||
|
|
||||||
TRIGGER_SCHEMA = vol.Any(TARGET_TRIGGER_SCHEMA, TOGGLE_TRIGGER_SCHEMA)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_get_triggers(
|
async def async_get_triggers(
|
||||||
hass: HomeAssistant, device_id: str
|
hass: HomeAssistant, device_id: str
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"device_automation": {
|
"device_automation": {
|
||||||
"trigger_type": {
|
"trigger_type": {
|
||||||
"target_humidity_changed": "{entity_name} target humidity changed",
|
"target_humidity_changed": "{entity_name} target humidity changed",
|
||||||
|
"toggled": "{entity_name} turned on or off",
|
||||||
"turned_on": "{entity_name} turned on",
|
"turned_on": "{entity_name} turned on",
|
||||||
"turned_off": "{entity_name} turned off"
|
"turned_off": "{entity_name} turned off"
|
||||||
},
|
},
|
||||||
|
@ -16,8 +16,9 @@ from homeassistant.helpers.typing import ConfigType
|
|||||||
|
|
||||||
from . import DOMAIN
|
from . import DOMAIN
|
||||||
|
|
||||||
TRIGGER_SCHEMA = toggle_entity.TRIGGER_SCHEMA.extend(
|
TRIGGER_SCHEMA = vol.All(
|
||||||
{vol.Required(CONF_DOMAIN): DOMAIN}
|
toggle_entity.TRIGGER_SCHEMA,
|
||||||
|
vol.Schema({vol.Required(CONF_DOMAIN): DOMAIN}, extra=vol.ALLOW_EXTRA),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
"is_off": "{entity_name} is off"
|
"is_off": "{entity_name} is off"
|
||||||
},
|
},
|
||||||
"trigger_type": {
|
"trigger_type": {
|
||||||
|
"toggled": "{entity_name} turned on or off",
|
||||||
"turned_on": "{entity_name} turned on",
|
"turned_on": "{entity_name} turned on",
|
||||||
"turned_off": "{entity_name} turned off"
|
"turned_off": "{entity_name} turned off"
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,9 @@ from homeassistant.helpers.typing import ConfigType
|
|||||||
|
|
||||||
from . import DOMAIN
|
from . import DOMAIN
|
||||||
|
|
||||||
TRIGGER_SCHEMA = toggle_entity.TRIGGER_SCHEMA.extend(
|
TRIGGER_SCHEMA = vol.All(
|
||||||
{vol.Required(CONF_DOMAIN): DOMAIN}
|
toggle_entity.TRIGGER_SCHEMA,
|
||||||
|
vol.Schema({vol.Required(CONF_DOMAIN): DOMAIN}, extra=vol.ALLOW_EXTRA),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"is_off": "{entity_name} is off"
|
"is_off": "{entity_name} is off"
|
||||||
},
|
},
|
||||||
"trigger_type": {
|
"trigger_type": {
|
||||||
|
"toggled": "{entity_name} turned on or off",
|
||||||
"turned_on": "{entity_name} turned on",
|
"turned_on": "{entity_name} turned on",
|
||||||
"turned_off": "{entity_name} turned off"
|
"turned_off": "{entity_name} turned off"
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,9 @@ from homeassistant.helpers.typing import ConfigType
|
|||||||
|
|
||||||
from . import DOMAIN
|
from . import DOMAIN
|
||||||
|
|
||||||
TRIGGER_SCHEMA = toggle_entity.TRIGGER_SCHEMA.extend(
|
TRIGGER_SCHEMA = vol.All(
|
||||||
{vol.Required(CONF_DOMAIN): DOMAIN}
|
toggle_entity.TRIGGER_SCHEMA,
|
||||||
|
vol.Schema({vol.Required(CONF_DOMAIN): DOMAIN}, extra=vol.ALLOW_EXTRA),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"is_off": "{entity_name} is off"
|
"is_off": "{entity_name} is off"
|
||||||
},
|
},
|
||||||
"trigger_type": {
|
"trigger_type": {
|
||||||
|
"toggled": "{entity_name} turned on or off",
|
||||||
"turned_on": "{entity_name} turned on",
|
"turned_on": "{entity_name} turned on",
|
||||||
"turned_off": "{entity_name} turned off"
|
"turned_off": "{entity_name} turned off"
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,13 @@ async def test_websocket_get_triggers(hass, hass_ws_client, device_reg, entity_r
|
|||||||
)
|
)
|
||||||
entity_reg.async_get_or_create("light", "test", "5678", device_id=device_entry.id)
|
entity_reg.async_get_or_create("light", "test", "5678", device_id=device_entry.id)
|
||||||
expected_triggers = [
|
expected_triggers = [
|
||||||
|
{
|
||||||
|
"platform": "device",
|
||||||
|
"domain": "light",
|
||||||
|
"type": "toggled",
|
||||||
|
"device_id": device_entry.id,
|
||||||
|
"entity_id": "light.test_5678",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"platform": "device",
|
"platform": "device",
|
||||||
"domain": "light",
|
"domain": "light",
|
||||||
@ -395,14 +402,14 @@ async def test_async_get_device_automations_single_device_trigger(
|
|||||||
hass, device_automation.DeviceAutomationType.TRIGGER, [device_entry.id]
|
hass, device_automation.DeviceAutomationType.TRIGGER, [device_entry.id]
|
||||||
)
|
)
|
||||||
assert device_entry.id in result
|
assert device_entry.id in result
|
||||||
assert len(result[device_entry.id]) == 2
|
assert len(result[device_entry.id]) == 3
|
||||||
|
|
||||||
# Test deprecated str automation_type works, to be removed in 2022.4
|
# Test deprecated str automation_type works, to be removed in 2022.4
|
||||||
result = await device_automation.async_get_device_automations(
|
result = await device_automation.async_get_device_automations(
|
||||||
hass, "trigger", [device_entry.id]
|
hass, "trigger", [device_entry.id]
|
||||||
)
|
)
|
||||||
assert device_entry.id in result
|
assert device_entry.id in result
|
||||||
assert len(result[device_entry.id]) == 2
|
assert len(result[device_entry.id]) == 3 # toggled, turned_on, turned_off
|
||||||
|
|
||||||
|
|
||||||
async def test_async_get_device_automations_all_devices_trigger(
|
async def test_async_get_device_automations_all_devices_trigger(
|
||||||
@ -421,7 +428,7 @@ async def test_async_get_device_automations_all_devices_trigger(
|
|||||||
hass, device_automation.DeviceAutomationType.TRIGGER
|
hass, device_automation.DeviceAutomationType.TRIGGER
|
||||||
)
|
)
|
||||||
assert device_entry.id in result
|
assert device_entry.id in result
|
||||||
assert len(result[device_entry.id]) == 2
|
assert len(result[device_entry.id]) == 3 # toggled, turned_on, turned_off
|
||||||
|
|
||||||
|
|
||||||
async def test_async_get_device_automations_all_devices_condition(
|
async def test_async_get_device_automations_all_devices_condition(
|
||||||
@ -520,7 +527,7 @@ async def test_websocket_get_trigger_capabilities(
|
|||||||
triggers = msg["result"]
|
triggers = msg["result"]
|
||||||
|
|
||||||
id = 2
|
id = 2
|
||||||
assert len(triggers) == 2
|
assert len(triggers) == 3 # toggled, turned_on, turned_off
|
||||||
for trigger in triggers:
|
for trigger in triggers:
|
||||||
await client.send_json(
|
await client.send_json(
|
||||||
{
|
{
|
||||||
|
199
tests/components/device_automation/test_toggle_entity.py
Normal file
199
tests/components/device_automation/test_toggle_entity.py
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
"""The test for device automation toggle entity helpers."""
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import homeassistant.components.automation as automation
|
||||||
|
from homeassistant.const import CONF_PLATFORM, STATE_OFF, STATE_ON
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
|
from tests.common import async_fire_time_changed, async_mock_service
|
||||||
|
from tests.components.blueprint.conftest import stub_blueprint_populate # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def calls(hass):
|
||||||
|
"""Track calls to a mock service."""
|
||||||
|
return async_mock_service(hass, "test", "automation")
|
||||||
|
|
||||||
|
|
||||||
|
async def test_if_fires_on_state_change(hass, calls, enable_custom_integrations):
|
||||||
|
"""Test for turn_on and turn_off triggers firing.
|
||||||
|
|
||||||
|
This is a sanity test for the toggle entity device automation helper, this is
|
||||||
|
tested by each integration too.
|
||||||
|
"""
|
||||||
|
platform = getattr(hass.components, "test.switch")
|
||||||
|
|
||||||
|
platform.init()
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass, "switch", {"switch": {CONF_PLATFORM: "test"}}
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
ent1, ent2, ent3 = platform.ENTITIES
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
automation.DOMAIN,
|
||||||
|
{
|
||||||
|
automation.DOMAIN: [
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"platform": "device",
|
||||||
|
"domain": "switch",
|
||||||
|
"device_id": "",
|
||||||
|
"entity_id": ent1.entity_id,
|
||||||
|
"type": "turned_on",
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data_template": {
|
||||||
|
"some": "turn_on {{ trigger.%s }}"
|
||||||
|
% "}} - {{ trigger.".join(
|
||||||
|
(
|
||||||
|
"platform",
|
||||||
|
"entity_id",
|
||||||
|
"from_state.state",
|
||||||
|
"to_state.state",
|
||||||
|
"for",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"platform": "device",
|
||||||
|
"domain": "switch",
|
||||||
|
"device_id": "",
|
||||||
|
"entity_id": ent1.entity_id,
|
||||||
|
"type": "turned_off",
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data_template": {
|
||||||
|
"some": "turn_off {{ trigger.%s }}"
|
||||||
|
% "}} - {{ trigger.".join(
|
||||||
|
(
|
||||||
|
"platform",
|
||||||
|
"entity_id",
|
||||||
|
"from_state.state",
|
||||||
|
"to_state.state",
|
||||||
|
"for",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"platform": "device",
|
||||||
|
"domain": "switch",
|
||||||
|
"device_id": "",
|
||||||
|
"entity_id": ent1.entity_id,
|
||||||
|
"type": "toggled",
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data_template": {
|
||||||
|
"some": "turn_on_or_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(ent1.entity_id).state == STATE_ON
|
||||||
|
assert len(calls) == 0
|
||||||
|
|
||||||
|
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(calls) == 2
|
||||||
|
assert {calls[0].data["some"], calls[1].data["some"]} == {
|
||||||
|
f"turn_off device - {ent1.entity_id} - on - off - None",
|
||||||
|
f"turn_on_or_off device - {ent1.entity_id} - on - off - None",
|
||||||
|
}
|
||||||
|
|
||||||
|
hass.states.async_set(ent1.entity_id, STATE_ON)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(calls) == 4
|
||||||
|
assert {calls[2].data["some"], calls[3].data["some"]} == {
|
||||||
|
f"turn_on device - {ent1.entity_id} - off - on - None",
|
||||||
|
f"turn_on_or_off device - {ent1.entity_id} - off - on - None",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("trigger", ["turned_off", "toggled"])
|
||||||
|
async def test_if_fires_on_state_change_with_for(
|
||||||
|
hass, calls, enable_custom_integrations, trigger
|
||||||
|
):
|
||||||
|
"""Test for triggers firing with delay."""
|
||||||
|
platform = getattr(hass.components, "test.switch")
|
||||||
|
|
||||||
|
platform.init()
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass, "switch", {"switch": {CONF_PLATFORM: "test"}}
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
ent1, ent2, ent3 = platform.ENTITIES
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
automation.DOMAIN,
|
||||||
|
{
|
||||||
|
automation.DOMAIN: [
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"platform": "device",
|
||||||
|
"domain": "switch",
|
||||||
|
"device_id": "",
|
||||||
|
"entity_id": ent1.entity_id,
|
||||||
|
"type": trigger,
|
||||||
|
"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(ent1.entity_id).state == STATE_ON
|
||||||
|
assert len(calls) == 0
|
||||||
|
|
||||||
|
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
||||||
|
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"] == "turn_off device - {} - on - off - 0:00:05".format(
|
||||||
|
ent1.entity_id
|
||||||
|
)
|
@ -66,6 +66,13 @@ async def test_get_triggers(hass, device_reg, entity_reg):
|
|||||||
"device_id": device_entry.id,
|
"device_id": device_entry.id,
|
||||||
"entity_id": f"{DOMAIN}.test_5678",
|
"entity_id": f"{DOMAIN}.test_5678",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"type": "toggled",
|
||||||
|
"device_id": device_entry.id,
|
||||||
|
"entity_id": f"{DOMAIN}.test_5678",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
triggers = await async_get_device_automations(
|
triggers = await async_get_device_automations(
|
||||||
hass, DeviceAutomationType.TRIGGER, device_entry.id
|
hass, DeviceAutomationType.TRIGGER, device_entry.id
|
||||||
@ -144,6 +151,25 @@ async def test_if_fires_on_state_change(hass, calls):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"device_id": "",
|
||||||
|
"entity_id": "fan.entity",
|
||||||
|
"type": "toggled",
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data_template": {
|
||||||
|
"some": (
|
||||||
|
"turn_on_or_off - {{ trigger.platform}} - "
|
||||||
|
"{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
|
||||||
|
"{{ trigger.to_state.state}} - {{ trigger.for }}"
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -151,14 +177,20 @@ async def test_if_fires_on_state_change(hass, calls):
|
|||||||
# Fake that the entity is turning on.
|
# Fake that the entity is turning on.
|
||||||
hass.states.async_set("fan.entity", STATE_ON)
|
hass.states.async_set("fan.entity", STATE_ON)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 1
|
assert len(calls) == 2
|
||||||
assert calls[0].data["some"] == "turn_on - device - fan.entity - off - on - None"
|
assert {calls[0].data["some"], calls[1].data["some"]} == {
|
||||||
|
"turn_on - device - fan.entity - off - on - None",
|
||||||
|
"turn_on_or_off - device - fan.entity - off - on - None",
|
||||||
|
}
|
||||||
|
|
||||||
# Fake that the entity is turning off.
|
# Fake that the entity is turning off.
|
||||||
hass.states.async_set("fan.entity", STATE_OFF)
|
hass.states.async_set("fan.entity", STATE_OFF)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 2
|
assert len(calls) == 4
|
||||||
assert calls[1].data["some"] == "turn_off - device - fan.entity - on - off - None"
|
assert {calls[2].data["some"], calls[3].data["some"]} == {
|
||||||
|
"turn_off - device - fan.entity - on - off - None",
|
||||||
|
"turn_on_or_off - device - fan.entity - on - off - None",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_if_fires_on_state_change_with_for(hass, calls):
|
async def test_if_fires_on_state_change_with_for(hass, calls):
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from homeassistant.components.device_automation import DeviceAutomationType
|
from homeassistant.components.device_automation import DeviceAutomationType
|
||||||
|
from homeassistant.components.homekit.const import CHAR_PROGRAMMABLE_SWITCH_EVENT
|
||||||
from homeassistant.components.homekit.type_triggers import DeviceTriggerAccessory
|
from homeassistant.components.homekit.type_triggers import DeviceTriggerAccessory
|
||||||
from homeassistant.const import STATE_OFF, STATE_ON
|
from homeassistant.const import STATE_OFF, STATE_ON
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
@ -50,11 +51,16 @@ async def test_programmable_switch_button_fires_on_trigger(
|
|||||||
hk_driver.publish.reset_mock()
|
hk_driver.publish.reset_mock()
|
||||||
hass.states.async_set("light.ceiling_lights", STATE_ON)
|
hass.states.async_set("light.ceiling_lights", STATE_ON)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
hk_driver.publish.assert_called_once()
|
assert len(hk_driver.publish.mock_calls) == 2 # one for on, one for toggle
|
||||||
|
for call in hk_driver.publish.mock_calls:
|
||||||
|
char = acc.get_characteristic(call.args[0]["aid"], call.args[0]["iid"])
|
||||||
|
assert char.display_name == CHAR_PROGRAMMABLE_SWITCH_EVENT
|
||||||
|
|
||||||
hk_driver.publish.reset_mock()
|
hk_driver.publish.reset_mock()
|
||||||
hass.states.async_set("light.ceiling_lights", STATE_OFF)
|
hass.states.async_set("light.ceiling_lights", STATE_OFF)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
hk_driver.publish.assert_called_once()
|
assert len(hk_driver.publish.mock_calls) == 2 # one for on, one for toggle
|
||||||
|
for call in hk_driver.publish.mock_calls:
|
||||||
|
char = acc.get_characteristic(call.args[0]["aid"], call.args[0]["iid"])
|
||||||
|
assert char.display_name == CHAR_PROGRAMMABLE_SWITCH_EVENT
|
||||||
await acc.stop()
|
await acc.stop()
|
||||||
|
@ -84,6 +84,13 @@ async def test_get_triggers(hass, device_reg, entity_reg):
|
|||||||
"device_id": device_entry.id,
|
"device_id": device_entry.id,
|
||||||
"entity_id": f"{DOMAIN}.test_5678",
|
"entity_id": f"{DOMAIN}.test_5678",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"type": "toggled",
|
||||||
|
"device_id": device_entry.id,
|
||||||
|
"entity_id": f"{DOMAIN}.test_5678",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
triggers = await async_get_device_automations(
|
triggers = await async_get_device_automations(
|
||||||
hass, DeviceAutomationType.TRIGGER, device_entry.id
|
hass, DeviceAutomationType.TRIGGER, device_entry.id
|
||||||
@ -200,6 +207,30 @@ async def test_if_fires_on_state_change(hass, calls):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"device_id": "",
|
||||||
|
"entity_id": "humidifier.entity",
|
||||||
|
"type": "toggled",
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data_template": {
|
||||||
|
"some": "turn_on_or_off {{ trigger.%s }}"
|
||||||
|
% "}} - {{ trigger.".join(
|
||||||
|
(
|
||||||
|
"platform",
|
||||||
|
"entity_id",
|
||||||
|
"from_state.state",
|
||||||
|
"to_state.state",
|
||||||
|
"for",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -225,18 +256,20 @@ async def test_if_fires_on_state_change(hass, calls):
|
|||||||
# Fake turn off
|
# Fake turn off
|
||||||
hass.states.async_set("humidifier.entity", STATE_OFF, {const.ATTR_HUMIDITY: 37})
|
hass.states.async_set("humidifier.entity", STATE_OFF, {const.ATTR_HUMIDITY: 37})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 4
|
assert len(calls) == 5
|
||||||
assert (
|
assert {calls[3].data["some"], calls[4].data["some"]} == {
|
||||||
calls[3].data["some"] == "turn_off device - humidifier.entity - on - off - None"
|
"turn_off device - humidifier.entity - on - off - None",
|
||||||
)
|
"turn_on_or_off device - humidifier.entity - on - off - None",
|
||||||
|
}
|
||||||
|
|
||||||
# Fake turn on
|
# Fake turn on
|
||||||
hass.states.async_set("humidifier.entity", STATE_ON, {const.ATTR_HUMIDITY: 37})
|
hass.states.async_set("humidifier.entity", STATE_ON, {const.ATTR_HUMIDITY: 37})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 5
|
assert len(calls) == 7
|
||||||
assert (
|
assert {calls[5].data["some"], calls[6].data["some"]} == {
|
||||||
calls[4].data["some"] == "turn_on device - humidifier.entity - off - on - None"
|
"turn_on device - humidifier.entity - off - on - None",
|
||||||
)
|
"turn_on_or_off device - humidifier.entity - off - on - None",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_invalid_config(hass, calls):
|
async def test_invalid_config(hass, calls):
|
||||||
|
@ -51,6 +51,13 @@ async def test_get_triggers(hass, device_reg, entity_reg):
|
|||||||
)
|
)
|
||||||
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
|
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
|
||||||
expected_triggers = [
|
expected_triggers = [
|
||||||
|
{
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"type": "toggled",
|
||||||
|
"device_id": device_entry.id,
|
||||||
|
"entity_id": f"{DOMAIN}.test_5678",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"platform": "device",
|
"platform": "device",
|
||||||
"domain": DOMAIN,
|
"domain": DOMAIN,
|
||||||
@ -161,6 +168,30 @@ async def test_if_fires_on_state_change(hass, calls, enable_custom_integrations)
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"device_id": "",
|
||||||
|
"entity_id": ent1.entity_id,
|
||||||
|
"type": "toggled",
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data_template": {
|
||||||
|
"some": "turn_on_or_off {{ trigger.%s }}"
|
||||||
|
% "}} - {{ trigger.".join(
|
||||||
|
(
|
||||||
|
"platform",
|
||||||
|
"entity_id",
|
||||||
|
"from_state.state",
|
||||||
|
"to_state.state",
|
||||||
|
"for",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -170,17 +201,19 @@ async def test_if_fires_on_state_change(hass, calls, enable_custom_integrations)
|
|||||||
|
|
||||||
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 1
|
assert len(calls) == 2
|
||||||
assert calls[0].data["some"] == "turn_off device - {} - on - off - None".format(
|
assert {calls[0].data["some"], calls[1].data["some"]} == {
|
||||||
ent1.entity_id
|
f"turn_off device - {ent1.entity_id} - on - off - None",
|
||||||
)
|
f"turn_on_or_off device - {ent1.entity_id} - on - off - None",
|
||||||
|
}
|
||||||
|
|
||||||
hass.states.async_set(ent1.entity_id, STATE_ON)
|
hass.states.async_set(ent1.entity_id, STATE_ON)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 2
|
assert len(calls) == 4
|
||||||
assert calls[1].data["some"] == "turn_on device - {} - off - on - None".format(
|
assert {calls[2].data["some"], calls[3].data["some"]} == {
|
||||||
ent1.entity_id
|
f"turn_on device - {ent1.entity_id} - off - on - None",
|
||||||
)
|
f"turn_on_or_off device - {ent1.entity_id} - off - on - None",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_if_fires_on_state_change_with_for(
|
async def test_if_fires_on_state_change_with_for(
|
||||||
|
@ -51,6 +51,13 @@ async def test_get_triggers(hass, device_reg, entity_reg):
|
|||||||
)
|
)
|
||||||
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
|
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
|
||||||
expected_triggers = [
|
expected_triggers = [
|
||||||
|
{
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"type": "toggled",
|
||||||
|
"device_id": device_entry.id,
|
||||||
|
"entity_id": f"{DOMAIN}.test_5678",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"platform": "device",
|
"platform": "device",
|
||||||
"domain": DOMAIN,
|
"domain": DOMAIN,
|
||||||
@ -159,6 +166,30 @@ async def test_if_fires_on_state_change(hass, calls, enable_custom_integrations)
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"device_id": "",
|
||||||
|
"entity_id": ent1.entity_id,
|
||||||
|
"type": "toggled",
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data_template": {
|
||||||
|
"some": "turn_on_or_off {{ trigger.%s }}"
|
||||||
|
% "}} - {{ trigger.".join(
|
||||||
|
(
|
||||||
|
"platform",
|
||||||
|
"entity_id",
|
||||||
|
"from_state.state",
|
||||||
|
"to_state.state",
|
||||||
|
"for",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -168,17 +199,19 @@ async def test_if_fires_on_state_change(hass, calls, enable_custom_integrations)
|
|||||||
|
|
||||||
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 1
|
assert len(calls) == 2
|
||||||
assert calls[0].data["some"] == "turn_off device - {} - on - off - None".format(
|
assert {calls[0].data["some"], calls[1].data["some"]} == {
|
||||||
ent1.entity_id
|
f"turn_off device - {ent1.entity_id} - on - off - None",
|
||||||
)
|
f"turn_on_or_off device - {ent1.entity_id} - on - off - None",
|
||||||
|
}
|
||||||
|
|
||||||
hass.states.async_set(ent1.entity_id, STATE_ON)
|
hass.states.async_set(ent1.entity_id, STATE_ON)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 2
|
assert len(calls) == 4
|
||||||
assert calls[1].data["some"] == "turn_on device - {} - off - on - None".format(
|
assert {calls[2].data["some"], calls[3].data["some"]} == {
|
||||||
ent1.entity_id
|
f"turn_on device - {ent1.entity_id} - off - on - None",
|
||||||
)
|
f"turn_on_or_off device - {ent1.entity_id} - off - on - None",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_if_fires_on_state_change_with_for(
|
async def test_if_fires_on_state_change_with_for(
|
||||||
|
@ -51,6 +51,13 @@ async def test_get_triggers(hass, device_reg, entity_reg):
|
|||||||
)
|
)
|
||||||
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
|
entity_reg.async_get_or_create(DOMAIN, "test", "5678", device_id=device_entry.id)
|
||||||
expected_triggers = [
|
expected_triggers = [
|
||||||
|
{
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"type": "toggled",
|
||||||
|
"device_id": device_entry.id,
|
||||||
|
"entity_id": f"{DOMAIN}.test_5678",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"platform": "device",
|
"platform": "device",
|
||||||
"domain": DOMAIN,
|
"domain": DOMAIN,
|
||||||
@ -159,6 +166,30 @@ async def test_if_fires_on_state_change(hass, calls, enable_custom_integrations)
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"trigger": {
|
||||||
|
"platform": "device",
|
||||||
|
"domain": DOMAIN,
|
||||||
|
"device_id": "",
|
||||||
|
"entity_id": ent1.entity_id,
|
||||||
|
"type": "toggled",
|
||||||
|
},
|
||||||
|
"action": {
|
||||||
|
"service": "test.automation",
|
||||||
|
"data_template": {
|
||||||
|
"some": "turn_on_or_off {{ trigger.%s }}"
|
||||||
|
% "}} - {{ trigger.".join(
|
||||||
|
(
|
||||||
|
"platform",
|
||||||
|
"entity_id",
|
||||||
|
"from_state.state",
|
||||||
|
"to_state.state",
|
||||||
|
"for",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -168,17 +199,19 @@ async def test_if_fires_on_state_change(hass, calls, enable_custom_integrations)
|
|||||||
|
|
||||||
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
hass.states.async_set(ent1.entity_id, STATE_OFF)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 1
|
assert len(calls) == 2
|
||||||
assert calls[0].data["some"] == "turn_off device - {} - on - off - None".format(
|
assert {calls[0].data["some"], calls[1].data["some"]} == {
|
||||||
ent1.entity_id
|
f"turn_off device - {ent1.entity_id} - on - off - None",
|
||||||
)
|
f"turn_on_or_off device - {ent1.entity_id} - on - off - None",
|
||||||
|
}
|
||||||
|
|
||||||
hass.states.async_set(ent1.entity_id, STATE_ON)
|
hass.states.async_set(ent1.entity_id, STATE_ON)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(calls) == 2
|
assert len(calls) == 4
|
||||||
assert calls[1].data["some"] == "turn_on device - {} - off - on - None".format(
|
assert {calls[2].data["some"], calls[3].data["some"]} == {
|
||||||
ent1.entity_id
|
f"turn_on device - {ent1.entity_id} - off - on - None",
|
||||||
)
|
f"turn_on_or_off device - {ent1.entity_id} - off - on - None",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_if_fires_on_state_change_with_for(
|
async def test_if_fires_on_state_change_with_for(
|
||||||
|
@ -66,6 +66,13 @@ async def test_get_triggers(hass, wemo_entity):
|
|||||||
CONF_PLATFORM: "device",
|
CONF_PLATFORM: "device",
|
||||||
CONF_TYPE: EVENT_TYPE_LONG_PRESS,
|
CONF_TYPE: EVENT_TYPE_LONG_PRESS,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
CONF_DEVICE_ID: wemo_entity.device_id,
|
||||||
|
CONF_DOMAIN: Platform.SWITCH,
|
||||||
|
CONF_ENTITY_ID: wemo_entity.entity_id,
|
||||||
|
CONF_PLATFORM: "device",
|
||||||
|
CONF_TYPE: "toggled",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
CONF_DEVICE_ID: wemo_entity.device_id,
|
CONF_DEVICE_ID: wemo_entity.device_id,
|
||||||
CONF_DOMAIN: Platform.SWITCH,
|
CONF_DOMAIN: Platform.SWITCH,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user