diff --git a/homeassistant/components/automation/__init__.py b/homeassistant/components/automation/__init__.py index f669d415854..3409ce832dd 100644 --- a/homeassistant/components/automation/__init__.py +++ b/homeassistant/components/automation/__init__.py @@ -7,9 +7,6 @@ from typing import Any, Awaitable, Callable import voluptuous as vol -from homeassistant.components.device_automation.exceptions import ( - InvalidDeviceAutomationConfig, -) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_NAME, @@ -476,10 +473,7 @@ async def _async_process_trigger(hass, config, trigger_configs, name, action): for conf in trigger_configs: platform = importlib.import_module(".{}".format(conf[CONF_PLATFORM]), __name__) - try: - remove = await platform.async_attach_trigger(hass, conf, action, info) - except InvalidDeviceAutomationConfig: - remove = False + remove = await platform.async_attach_trigger(hass, conf, action, info) if not remove: _LOGGER.error("Error setting up trigger %s", name) diff --git a/homeassistant/components/automation/config.py b/homeassistant/components/automation/config.py index ebbd1771e84..5733cd2e83e 100644 --- a/homeassistant/components/automation/config.py +++ b/homeassistant/components/automation/config.py @@ -4,6 +4,9 @@ import importlib import voluptuous as vol +from homeassistant.components.device_automation.exceptions import ( + InvalidDeviceAutomationConfig, +) from homeassistant.const import CONF_PLATFORM from homeassistant.config import async_log_exception, config_without_domain from homeassistant.exceptions import HomeAssistantError @@ -52,7 +55,12 @@ async def _try_async_validate_config_item(hass, config, full_config=None): """Validate config item.""" try: config = await async_validate_config_item(hass, config, full_config) - except (vol.Invalid, HomeAssistantError, IntegrationNotFound) as ex: + except ( + vol.Invalid, + HomeAssistantError, + IntegrationNotFound, + InvalidDeviceAutomationConfig, + ) as ex: async_log_exception(ex, DOMAIN, full_config or config, hass) return None diff --git a/homeassistant/components/automation/device.py b/homeassistant/components/automation/device.py index dc65008c3fb..ced8f65cbf5 100644 --- a/homeassistant/components/automation/device.py +++ b/homeassistant/components/automation/device.py @@ -18,6 +18,9 @@ async def async_validate_trigger_config(hass, config): platform = await async_get_device_automation_platform( hass, config[CONF_DOMAIN], "trigger" ) + if hasattr(platform, "async_validate_trigger_config"): + return await getattr(platform, "async_validate_trigger_config")(hass, config) + return platform.TRIGGER_SCHEMA(config) diff --git a/homeassistant/components/deconz/device_trigger.py b/homeassistant/components/deconz/device_trigger.py index 9f66cf156aa..27ff6fcd590 100644 --- a/homeassistant/components/deconz/device_trigger.py +++ b/homeassistant/components/deconz/device_trigger.py @@ -204,8 +204,10 @@ def _get_deconz_event_from_device_id(hass, device_id): return None -async def async_attach_trigger(hass, config, action, automation_info): - """Listen for state changes based on configuration.""" +async def async_validate_trigger_config(hass, config): + """Validate config.""" + config = TRIGGER_SCHEMA(config) + device_registry = await hass.helpers.device_registry.async_get_registry() device = device_registry.async_get(config[CONF_DEVICE_ID]) @@ -214,6 +216,16 @@ async def async_attach_trigger(hass, config, action, automation_info): if device.model not in REMOTES or trigger not in REMOTES[device.model]: raise InvalidDeviceAutomationConfig + return config + + +async def async_attach_trigger(hass, config, action, automation_info): + """Listen for state changes based on configuration.""" + device_registry = await hass.helpers.device_registry.async_get_registry() + device = device_registry.async_get(config[CONF_DEVICE_ID]) + + trigger = (config[CONF_TYPE], config[CONF_SUBTYPE]) + trigger = REMOTES[device.model][trigger] deconz_event = _get_deconz_event_from_device_id(hass, device.id) diff --git a/homeassistant/components/zha/device_trigger.py b/homeassistant/components/zha/device_trigger.py index ddf7465e0c0..8d74ae108a2 100644 --- a/homeassistant/components/zha/device_trigger.py +++ b/homeassistant/components/zha/device_trigger.py @@ -21,8 +21,10 @@ TRIGGER_SCHEMA = TRIGGER_BASE_SCHEMA.extend( ) -async def async_attach_trigger(hass, config, action, automation_info): - """Listen for state changes based on configuration.""" +async def async_validate_trigger_config(hass, config): + """Validate config.""" + config = TRIGGER_SCHEMA(config) + trigger = (config[CONF_TYPE], config[CONF_SUBTYPE]) zha_device = await async_get_zha_device(hass, config[CONF_DEVICE_ID]) @@ -32,6 +34,14 @@ async def async_attach_trigger(hass, config, action, automation_info): ): raise InvalidDeviceAutomationConfig + return config + + +async def async_attach_trigger(hass, config, action, automation_info): + """Listen for state changes based on configuration.""" + trigger = (config[CONF_TYPE], config[CONF_SUBTYPE]) + zha_device = await async_get_zha_device(hass, config[CONF_DEVICE_ID]) + trigger = zha_device.device_automation_triggers[trigger] event_config = { diff --git a/tests/components/zha/test_device_trigger.py b/tests/components/zha/test_device_trigger.py index 2f4ddb6b8b2..8df1a072801 100644 --- a/tests/components/zha/test_device_trigger.py +++ b/tests/components/zha/test_device_trigger.py @@ -1,6 +1,4 @@ """ZHA device automation trigger tests.""" -from unittest.mock import patch - import pytest import homeassistant.components.automation as automation @@ -197,7 +195,7 @@ async def test_if_fires_on_event(hass, config_entry, zha_gateway, calls): assert calls[0].data["message"] == "service called" -async def test_exception_no_triggers(hass, config_entry, zha_gateway, calls): +async def test_exception_no_triggers(hass, config_entry, zha_gateway, calls, caplog): """Test for exception on event triggers firing.""" from zigpy.zcl.clusters.general import OnOff, Basic @@ -219,33 +217,32 @@ async def test_exception_no_triggers(hass, config_entry, zha_gateway, calls): ha_device_registry = await async_get_registry(hass) reg_device = ha_device_registry.async_get_device({("zha", ieee_address)}, set()) - with patch("logging.Logger.error") as mock: - await async_setup_component( - hass, - automation.DOMAIN, - { - automation.DOMAIN: [ - { - "trigger": { - "device_id": reg_device.id, - "domain": "zha", - "platform": "device", - "type": "junk", - "subtype": "junk", - }, - "action": { - "service": "test.automation", - "data": {"message": "service called"}, - }, - } - ] - }, - ) - await hass.async_block_till_done() - mock.assert_called_with("Error setting up trigger %s", "automation 0") + await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: [ + { + "trigger": { + "device_id": reg_device.id, + "domain": "zha", + "platform": "device", + "type": "junk", + "subtype": "junk", + }, + "action": { + "service": "test.automation", + "data": {"message": "service called"}, + }, + } + ] + }, + ) + await hass.async_block_till_done() + assert "Invalid config for [automation]" in caplog.text -async def test_exception_bad_trigger(hass, config_entry, zha_gateway, calls): +async def test_exception_bad_trigger(hass, config_entry, zha_gateway, calls, caplog): """Test for exception on event triggers firing.""" from zigpy.zcl.clusters.general import OnOff, Basic @@ -275,27 +272,26 @@ async def test_exception_bad_trigger(hass, config_entry, zha_gateway, calls): ha_device_registry = await async_get_registry(hass) reg_device = ha_device_registry.async_get_device({("zha", ieee_address)}, set()) - with patch("logging.Logger.error") as mock: - await async_setup_component( - hass, - automation.DOMAIN, - { - automation.DOMAIN: [ - { - "trigger": { - "device_id": reg_device.id, - "domain": "zha", - "platform": "device", - "type": "junk", - "subtype": "junk", - }, - "action": { - "service": "test.automation", - "data": {"message": "service called"}, - }, - } - ] - }, - ) - await hass.async_block_till_done() - mock.assert_called_with("Error setting up trigger %s", "automation 0") + await async_setup_component( + hass, + automation.DOMAIN, + { + automation.DOMAIN: [ + { + "trigger": { + "device_id": reg_device.id, + "domain": "zha", + "platform": "device", + "type": "junk", + "subtype": "junk", + }, + "action": { + "service": "test.automation", + "data": {"message": "service called"}, + }, + } + ] + }, + ) + await hass.async_block_till_done() + assert "Invalid config for [automation]" in caplog.text