Support async validation of device trigger (#27333)

pull/27370/head
Erik Montnemery 2019-10-09 21:04:11 +02:00 committed by GitHub
parent 3194dd3456
commit fdf4f398a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 64 deletions

View File

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

View File

@ -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

View File

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

View File

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

View File

@ -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 = {

View File

@ -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