1 """Offer knx telegram automation triggers."""
3 from typing
import Final
5 import voluptuous
as vol
6 from xknx.dpt
import DPTBase
7 from xknx.telegram
import Telegram, TelegramDirection
8 from xknx.telegram.address
import DeviceGroupAddress, parse_device_group_address
9 from xknx.telegram.apci
import GroupValueRead, GroupValueResponse, GroupValueWrite
18 from .const
import DOMAIN
19 from .schema
import ga_validator
20 from .telegrams
import SIGNAL_KNX_TELEGRAM, TelegramDict, decode_telegram_payload
21 from .validation
import dpt_base_type_validator
23 TRIGGER_TELEGRAM: Final =
"telegram"
25 PLATFORM_TYPE_TRIGGER_TELEGRAM: Final = f
"{DOMAIN}.{TRIGGER_TELEGRAM}"
27 CONF_KNX_DESTINATION: Final =
"destination"
28 CONF_KNX_GROUP_VALUE_WRITE: Final =
"group_value_write"
29 CONF_KNX_GROUP_VALUE_READ: Final =
"group_value_read"
30 CONF_KNX_GROUP_VALUE_RESPONSE: Final =
"group_value_response"
31 CONF_KNX_INCOMING: Final =
"incoming"
32 CONF_KNX_OUTGOING: Final =
"outgoing"
35 TELEGRAM_TRIGGER_SCHEMA: VolDictType = {
36 vol.Optional(CONF_KNX_DESTINATION): vol.All(cv.ensure_list, [ga_validator]),
37 vol.Optional(CONF_KNX_GROUP_VALUE_WRITE, default=
True): cv.boolean,
38 vol.Optional(CONF_KNX_GROUP_VALUE_RESPONSE, default=
True): cv.boolean,
39 vol.Optional(CONF_KNX_GROUP_VALUE_READ, default=
True): cv.boolean,
40 vol.Optional(CONF_KNX_INCOMING, default=
True): cv.boolean,
41 vol.Optional(CONF_KNX_OUTGOING, default=
True): cv.boolean,
44 TRIGGER_SCHEMA = cv.TRIGGER_BASE_SCHEMA.extend(
46 vol.Required(CONF_PLATFORM): PLATFORM_TYPE_TRIGGER_TELEGRAM,
47 vol.Optional(CONF_TYPE, default=
None): vol.Any(dpt_base_type_validator,
None),
48 **TELEGRAM_TRIGGER_SCHEMA,
56 action: TriggerActionType,
57 trigger_info: TriggerInfo,
59 """Listen for telegrams based on configuration."""
60 _addresses: list[str] = config.get(CONF_KNX_DESTINATION, [])
61 dst_addresses: list[DeviceGroupAddress] = [
62 parse_device_group_address(address)
for address
in _addresses
64 _transcoder = config.get(CONF_TYPE)
65 trigger_transcoder = DPTBase.parse_transcoder(_transcoder)
if _transcoder
else None
67 job =
HassJob(action, f
"KNX trigger {trigger_info}")
68 trigger_data = trigger_info[
"trigger_data"]
71 def async_call_trigger_action(
72 telegram: Telegram, telegram_dict: TelegramDict
74 """Filter Telegram and call trigger action."""
75 payload_apci = type(telegram.payload)
76 if payload_apci
is GroupValueWrite:
77 if config[CONF_KNX_GROUP_VALUE_WRITE]
is False:
79 elif payload_apci
is GroupValueResponse:
80 if config[CONF_KNX_GROUP_VALUE_RESPONSE]
is False:
82 elif payload_apci
is GroupValueRead:
83 if config[CONF_KNX_GROUP_VALUE_READ]
is False:
86 if telegram.direction
is TelegramDirection.INCOMING:
87 if config[CONF_KNX_INCOMING]
is False:
89 elif config[CONF_KNX_OUTGOING]
is False:
92 if dst_addresses
and telegram.destination_address
not in dst_addresses:
96 trigger_transcoder
is not None
97 and payload_apci
in (GroupValueWrite, GroupValueResponse)
98 and trigger_transcoder.value_type != telegram_dict[
"dpt_name"]
101 payload=telegram.payload.value,
102 transcoder=trigger_transcoder,
105 telegram_trigger_data = {**trigger_data, **telegram_dict, **decoded_payload}
107 telegram_trigger_data = {**trigger_data, **telegram_dict}
109 hass.async_run_hass_job(job, {
"trigger": telegram_trigger_data})
113 signal=SIGNAL_KNX_TELEGRAM,
114 target=async_call_trigger_action,
DecodedTelegramPayload decode_telegram_payload(DPTArray|DPTBinary payload, type[DPTBase] transcoder)
CALLBACK_TYPE async_attach_trigger(HomeAssistant hass, ConfigType config, TriggerActionType action, TriggerInfo trigger_info)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)