Files
core/tests/components/knx/test_trigger.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

342 lines
11 KiB
Python
Raw Permalink Normal View History

"""Tests for KNX integration specific triggers."""
import logging
import pytest
from homeassistant.components import automation
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.setup import async_setup_component
from .conftest import KNXTestKit
async def test_telegram_trigger(
hass: HomeAssistant,
service_calls: list[ServiceCall],
knx: KNXTestKit,
) -> None:
"""Test telegram triggers firing."""
await knx.setup_integration()
# "id" field added to action to test if `trigger_data` passed correctly in `async_attach_trigger`
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
# "catch_all" trigger
{
"trigger": {
"platform": "knx.telegram",
},
"action": {
"service": "test.automation",
"data_template": {
"catch_all": ("telegram - {{ trigger.destination }}"),
"id": (" {{ trigger.id }}"),
},
},
},
# "specific" trigger
{
"trigger": {
"platform": "knx.telegram",
"id": "test-id",
"destination": ["1/2/3", 2564], # 2564 -> "1/2/4" in raw format
"group_value_write": True,
"group_value_response": False,
"group_value_read": False,
"incoming": True,
"outgoing": True,
},
"action": {
"service": "test.automation",
"data_template": {
"specific": ("telegram - {{ trigger.destination }}"),
"id": (" {{ trigger.id }}"),
},
},
},
]
},
)
# "specific" shall ignore destination address
await knx.receive_write("0/0/1", (0x03, 0x2F))
assert len(service_calls) == 1
test_call = service_calls.pop()
assert test_call.data["catch_all"] == "telegram - 0/0/1"
assert test_call.data["id"] == 0
await knx.receive_write("1/2/4", (0x03, 0x2F))
assert len(service_calls) == 2
test_call = service_calls.pop()
assert test_call.data["specific"] == "telegram - 1/2/4"
assert test_call.data["id"] == "test-id"
test_call = service_calls.pop()
assert test_call.data["catch_all"] == "telegram - 1/2/4"
assert test_call.data["id"] == 0
# "specific" shall ignore GroupValueRead
await knx.receive_read("1/2/4")
assert len(service_calls) == 1
test_call = service_calls.pop()
assert test_call.data["catch_all"] == "telegram - 1/2/4"
assert test_call.data["id"] == 0
@pytest.mark.parametrize(
("payload", "type_option", "expected_value", "expected_unit"),
[
((0x4C,), {"type": "percent"}, 30, "%"),
((0x03,), {}, None, None), # "dpt" omitted defaults to None
((0x0C, 0x1A), {"type": "temperature"}, 21.00, "°C"),
],
)
async def test_telegram_trigger_dpt_option(
hass: HomeAssistant,
service_calls: list[ServiceCall],
knx: KNXTestKit,
payload: tuple[int, ...],
type_option: dict[str, bool],
expected_value: int | None,
expected_unit: str | None,
) -> None:
"""Test telegram trigger type option."""
await knx.setup_integration()
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
# "catch_all" trigger
{
"trigger": {
"platform": "knx.telegram",
**type_option,
},
"action": {
"service": "test.automation",
"data_template": {
"catch_all": ("telegram - {{ trigger.destination }}"),
"trigger": (" {{ trigger }}"),
},
},
},
]
},
)
await knx.receive_write("0/0/1", payload)
assert len(service_calls) == 1
test_call = service_calls.pop()
assert test_call.data["catch_all"] == "telegram - 0/0/1"
assert test_call.data["trigger"]["value"] == expected_value
assert test_call.data["trigger"]["unit"] == expected_unit
await knx.receive_read("0/0/1")
assert len(service_calls) == 1
test_call = service_calls.pop()
assert test_call.data["catch_all"] == "telegram - 0/0/1"
assert test_call.data["trigger"]["value"] is None
assert test_call.data["trigger"]["unit"] is None
@pytest.mark.parametrize(
"group_value_options",
[
{
"group_value_write": True,
"group_value_response": True,
"group_value_read": False,
},
{
"group_value_write": False,
"group_value_response": False,
"group_value_read": True,
},
{
# "group_value_write": True, # omitted defaults to True
"group_value_response": False,
"group_value_read": False,
},
],
)
@pytest.mark.parametrize(
"direction_options",
[
{
"incoming": True,
"outgoing": True,
},
{
# "incoming": True, # omitted defaults to True
"outgoing": False,
},
{
"incoming": False,
"outgoing": True,
},
],
)
async def test_telegram_trigger_options(
hass: HomeAssistant,
service_calls: list[ServiceCall],
knx: KNXTestKit,
group_value_options: dict[str, bool],
direction_options: dict[str, bool],
) -> None:
"""Test telegram trigger options."""
await knx.setup_integration()
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
# "catch_all" trigger
{
"trigger": {
"platform": "knx.telegram",
**group_value_options,
**direction_options,
},
"action": {
"service": "test.automation",
"data_template": {
"catch_all": ("telegram - {{ trigger.destination }}"),
},
},
},
]
},
)
await knx.receive_write("0/0/1", 1)
if group_value_options.get("group_value_write", True) and direction_options.get(
"incoming", True
):
assert len(service_calls) == 1
assert service_calls.pop().data["catch_all"] == "telegram - 0/0/1"
else:
assert len(service_calls) == 0
await knx.receive_response("0/0/1", 1)
if group_value_options["group_value_response"] and direction_options.get(
"incoming", True
):
assert len(service_calls) == 1
assert service_calls.pop().data["catch_all"] == "telegram - 0/0/1"
else:
assert len(service_calls) == 0
await knx.receive_read("0/0/1")
if group_value_options["group_value_read"] and direction_options.get(
"incoming", True
):
assert len(service_calls) == 1
assert service_calls.pop().data["catch_all"] == "telegram - 0/0/1"
else:
assert len(service_calls) == 0
await hass.services.async_call(
"knx",
"send",
{"address": "0/0/1", "payload": True},
blocking=True,
)
assert len(service_calls) == 1
await knx.assert_write("0/0/1", True)
if (
group_value_options.get("group_value_write", True)
and direction_options["outgoing"]
):
assert len(service_calls) == 2
assert service_calls.pop().data["catch_all"] == "telegram - 0/0/1"
else:
assert len(service_calls) == 1
async def test_remove_telegram_trigger(
hass: HomeAssistant,
service_calls: list[ServiceCall],
knx: KNXTestKit,
) -> None:
"""Test for removed callback when telegram trigger not used."""
automation_name = "telegram_trigger_automation"
await knx.setup_integration()
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"alias": automation_name,
"trigger": {
"platform": "knx.telegram",
},
"action": {
"service": "test.automation",
"data_template": {
"catch_all": ("telegram - {{ trigger.destination }}")
},
},
}
]
},
)
await knx.receive_write("0/0/1", (0x03, 0x2F))
assert len(service_calls) == 1
assert service_calls.pop().data["catch_all"] == "telegram - 0/0/1"
await hass.services.async_call(
automation.DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: f"automation.{automation_name}"},
blocking=True,
)
assert len(service_calls) == 1
await knx.receive_write("0/0/1", (0x03, 0x2F))
assert len(service_calls) == 1
async def test_invalid_trigger(
hass: HomeAssistant,
knx: KNXTestKit,
caplog: pytest.LogCaptureFixture,
) -> None:
"""Test invalid telegram trigger configuration."""
await knx.setup_integration()
caplog.clear()
with caplog.at_level(logging.ERROR):
assert await async_setup_component(
hass,
automation.DOMAIN,
{
automation.DOMAIN: [
{
"trigger": {
"platform": "knx.telegram",
"invalid": True,
},
"action": {
"service": "test.automation",
"data_template": {
"catch_all": ("telegram - {{ trigger.destination }}"),
},
},
},
]
},
)
assert (
"Unnamed automation failed to setup triggers and has been disabled: "
"extra keys not allowed @ data['invalid']. Got None"
in caplog.records[0].message
)