core/tests/components/knx/test_trigger.py

342 lines
11 KiB
Python

"""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
)