Reorganize trigger code (#38655)
This commit is contained in:
parent
fca071742d
commit
ca9dd0c833
51 changed files with 306 additions and 194 deletions
|
@ -8,8 +8,9 @@ from homeassistant.components.alarm_control_panel.const import (
|
|||
SUPPORT_ALARM_ARM_HOME,
|
||||
SUPPORT_ALARM_ARM_NIGHT,
|
||||
)
|
||||
from homeassistant.components.automation import AutomationActionType, state
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.homeassistant.triggers import state as state_trigger
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_ID,
|
||||
CONF_DOMAIN,
|
||||
|
@ -151,13 +152,13 @@ async def async_attach_trigger(
|
|||
to_state = STATE_ALARM_ARMED_NIGHT
|
||||
|
||||
state_config = {
|
||||
state.CONF_PLATFORM: "state",
|
||||
state_trigger.CONF_PLATFORM: "state",
|
||||
CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state.CONF_TO: to_state,
|
||||
state_trigger.CONF_TO: to_state,
|
||||
}
|
||||
if from_state:
|
||||
state_config[state.CONF_FROM] = from_state
|
||||
state_config = state.TRIGGER_SCHEMA(state_config)
|
||||
return await state.async_attach_trigger(
|
||||
state_config[state_trigger.CONF_FROM] = from_state
|
||||
state_config = state_trigger.TRIGGER_SCHEMA(state_config)
|
||||
return await state_trigger.async_attach_trigger(
|
||||
hass, state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
"""Allow to set up simple automation rules via the config file."""
|
||||
import asyncio
|
||||
import importlib
|
||||
import logging
|
||||
from typing import Any, Awaitable, Callable, List, Optional, Set
|
||||
from typing import Any, Awaitable, Callable, List, Optional, Set, cast
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
|
@ -46,6 +44,7 @@ from homeassistant.helpers.script import (
|
|||
make_script_schema,
|
||||
)
|
||||
from homeassistant.helpers.service import async_register_admin_service
|
||||
from homeassistant.helpers.trigger import async_initialize_triggers
|
||||
from homeassistant.helpers.typing import TemplateVarsType
|
||||
from homeassistant.loader import bind_hass
|
||||
from homeassistant.util.dt import parse_datetime, utcnow
|
||||
|
@ -90,26 +89,6 @@ _LOGGER = logging.getLogger(__name__)
|
|||
AutomationActionType = Callable[[HomeAssistant, TemplateVarsType], Awaitable[None]]
|
||||
|
||||
|
||||
def _platform_validator(config):
|
||||
"""Validate it is a valid platform."""
|
||||
try:
|
||||
platform = importlib.import_module(f".{config[CONF_PLATFORM]}", __name__)
|
||||
except ImportError:
|
||||
raise vol.Invalid("Invalid platform specified") from None
|
||||
|
||||
return platform.TRIGGER_SCHEMA(config)
|
||||
|
||||
|
||||
_TRIGGER_SCHEMA = vol.All(
|
||||
cv.ensure_list,
|
||||
[
|
||||
vol.All(
|
||||
vol.Schema({vol.Required(CONF_PLATFORM): str}, extra=vol.ALLOW_EXTRA),
|
||||
_platform_validator,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
_CONDITION_SCHEMA = vol.All(cv.ensure_list, [cv.CONDITION_SCHEMA])
|
||||
|
||||
PLATFORM_SCHEMA = vol.All(
|
||||
|
@ -122,7 +101,7 @@ PLATFORM_SCHEMA = vol.All(
|
|||
vol.Optional(CONF_DESCRIPTION): cv.string,
|
||||
vol.Optional(CONF_INITIAL_STATE): cv.boolean,
|
||||
vol.Optional(CONF_HIDE_ENTITY): cv.boolean,
|
||||
vol.Required(CONF_TRIGGER): _TRIGGER_SCHEMA,
|
||||
vol.Required(CONF_TRIGGER): cv.TRIGGER_SCHEMA,
|
||||
vol.Optional(CONF_CONDITION): _CONDITION_SCHEMA,
|
||||
vol.Required(CONF_ACTION): cv.SCRIPT_SCHEMA,
|
||||
},
|
||||
|
@ -485,36 +464,19 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
|
|||
self, home_assistant_start: bool
|
||||
) -> Optional[Callable[[], None]]:
|
||||
"""Set up the triggers."""
|
||||
info = {"name": self._name, "home_assistant_start": home_assistant_start}
|
||||
|
||||
triggers = []
|
||||
for conf in self._trigger_config:
|
||||
platform = importlib.import_module(f".{conf[CONF_PLATFORM]}", __name__)
|
||||
def log_cb(level, msg):
|
||||
self._logger.log(level, "%s %s", msg, self._name)
|
||||
|
||||
triggers.append(
|
||||
platform.async_attach_trigger( # type: ignore
|
||||
self.hass, conf, self.async_trigger, info
|
||||
)
|
||||
)
|
||||
|
||||
results = await asyncio.gather(*triggers)
|
||||
|
||||
if None in results:
|
||||
self._logger.error("Error setting up trigger %s", self._name)
|
||||
|
||||
removes = [remove for remove in results if remove is not None]
|
||||
if not removes:
|
||||
return None
|
||||
|
||||
self._logger.info("Initialized trigger %s", self._name)
|
||||
|
||||
@callback
|
||||
def remove_triggers():
|
||||
"""Remove attached triggers."""
|
||||
for remove in removes:
|
||||
remove()
|
||||
|
||||
return remove_triggers
|
||||
return await async_initialize_triggers(
|
||||
cast(HomeAssistant, self.hass),
|
||||
self._trigger_config,
|
||||
self.async_trigger,
|
||||
DOMAIN,
|
||||
self._name,
|
||||
log_cb,
|
||||
home_assistant_start,
|
||||
)
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
"""Config validation helper for the automation integration."""
|
||||
import asyncio
|
||||
import importlib
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
|
@ -8,10 +7,11 @@ from homeassistant.components.device_automation.exceptions import (
|
|||
InvalidDeviceAutomationConfig,
|
||||
)
|
||||
from homeassistant.config import async_log_exception, config_without_domain
|
||||
from homeassistant.const import CONF_PLATFORM
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import condition, config_per_platform
|
||||
from homeassistant.helpers import config_per_platform
|
||||
from homeassistant.helpers.condition import async_validate_condition_config
|
||||
from homeassistant.helpers.script import async_validate_action_config
|
||||
from homeassistant.helpers.trigger import async_validate_trigger_config
|
||||
from homeassistant.loader import IntegrationNotFound
|
||||
|
||||
from . import CONF_ACTION, CONF_CONDITION, CONF_TRIGGER, DOMAIN, PLATFORM_SCHEMA
|
||||
|
@ -24,22 +24,14 @@ async def async_validate_config_item(hass, config, full_config=None):
|
|||
"""Validate config item."""
|
||||
config = PLATFORM_SCHEMA(config)
|
||||
|
||||
triggers = []
|
||||
for trigger in config[CONF_TRIGGER]:
|
||||
trigger_platform = importlib.import_module(
|
||||
f"..{trigger[CONF_PLATFORM]}", __name__
|
||||
)
|
||||
if hasattr(trigger_platform, "async_validate_trigger_config"):
|
||||
trigger = await trigger_platform.async_validate_trigger_config(
|
||||
hass, trigger
|
||||
)
|
||||
triggers.append(trigger)
|
||||
config[CONF_TRIGGER] = triggers
|
||||
config[CONF_TRIGGER] = await async_validate_trigger_config(
|
||||
hass, config[CONF_TRIGGER]
|
||||
)
|
||||
|
||||
if CONF_CONDITION in config:
|
||||
config[CONF_CONDITION] = await asyncio.gather(
|
||||
*[
|
||||
condition.async_validate_condition_config(hass, cond)
|
||||
async_validate_condition_config(hass, cond)
|
||||
for cond in config[CONF_CONDITION]
|
||||
]
|
||||
)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
"""Provides device triggers for binary sensors."""
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.automation import state as state_automation
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.device_automation.const import (
|
||||
CONF_TURNED_OFF,
|
||||
CONF_TURNED_ON,
|
||||
)
|
||||
from homeassistant.components.homeassistant.triggers import state as state_trigger
|
||||
from homeassistant.const import ATTR_DEVICE_CLASS, CONF_ENTITY_ID, CONF_FOR, CONF_TYPE
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.entity_registry import async_entries_for_device
|
||||
|
@ -197,16 +197,16 @@ async def async_attach_trigger(hass, config, action, automation_info):
|
|||
to_state = "off"
|
||||
|
||||
state_config = {
|
||||
state_automation.CONF_PLATFORM: "state",
|
||||
state_automation.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state_automation.CONF_FROM: from_state,
|
||||
state_automation.CONF_TO: to_state,
|
||||
state_trigger.CONF_PLATFORM: "state",
|
||||
state_trigger.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state_trigger.CONF_FROM: from_state,
|
||||
state_trigger.CONF_TO: to_state,
|
||||
}
|
||||
if CONF_FOR in config:
|
||||
state_config[CONF_FOR] = config[CONF_FOR]
|
||||
|
||||
state_config = state_automation.TRIGGER_SCHEMA(state_config)
|
||||
return await state_automation.async_attach_trigger(
|
||||
state_config = state_trigger.TRIGGER_SCHEMA(state_config)
|
||||
return await state_trigger.async_attach_trigger(
|
||||
hass, state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@ from typing import List
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.automation import (
|
||||
AutomationActionType,
|
||||
numeric_state as numeric_state_automation,
|
||||
state as state_automation,
|
||||
)
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.homeassistant.triggers import (
|
||||
numeric_state as numeric_state_trigger,
|
||||
state as state_trigger,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_ABOVE,
|
||||
CONF_BELOW,
|
||||
|
@ -36,7 +36,7 @@ HVAC_MODE_TRIGGER_SCHEMA = TRIGGER_BASE_SCHEMA.extend(
|
|||
{
|
||||
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
||||
vol.Required(CONF_TYPE): "hvac_mode_changed",
|
||||
vol.Required(state_automation.CONF_TO): vol.In(const.HVAC_MODES),
|
||||
vol.Required(state_trigger.CONF_TO): vol.In(const.HVAC_MODES),
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -118,34 +118,34 @@ async def async_attach_trigger(
|
|||
|
||||
if trigger_type == "hvac_mode_changed":
|
||||
state_config = {
|
||||
state_automation.CONF_PLATFORM: "state",
|
||||
state_automation.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state_automation.CONF_TO: config[state_automation.CONF_TO],
|
||||
state_automation.CONF_FROM: [
|
||||
state_trigger.CONF_PLATFORM: "state",
|
||||
state_trigger.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state_trigger.CONF_TO: config[state_trigger.CONF_TO],
|
||||
state_trigger.CONF_FROM: [
|
||||
mode
|
||||
for mode in const.HVAC_MODES
|
||||
if mode != config[state_automation.CONF_TO]
|
||||
if mode != config[state_trigger.CONF_TO]
|
||||
],
|
||||
}
|
||||
if CONF_FOR in config:
|
||||
state_config[CONF_FOR] = config[CONF_FOR]
|
||||
state_config = state_automation.TRIGGER_SCHEMA(state_config)
|
||||
return await state_automation.async_attach_trigger(
|
||||
state_config = state_trigger.TRIGGER_SCHEMA(state_config)
|
||||
return await state_trigger.async_attach_trigger(
|
||||
hass, state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
numeric_state_config = {
|
||||
numeric_state_automation.CONF_PLATFORM: "numeric_state",
|
||||
numeric_state_automation.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
numeric_state_trigger.CONF_PLATFORM: "numeric_state",
|
||||
numeric_state_trigger.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
}
|
||||
|
||||
if trigger_type == "current_temperature_changed":
|
||||
numeric_state_config[
|
||||
numeric_state_automation.CONF_VALUE_TEMPLATE
|
||||
numeric_state_trigger.CONF_VALUE_TEMPLATE
|
||||
] = "{{ state.attributes.current_temperature }}"
|
||||
else:
|
||||
numeric_state_config[
|
||||
numeric_state_automation.CONF_VALUE_TEMPLATE
|
||||
numeric_state_trigger.CONF_VALUE_TEMPLATE
|
||||
] = "{{ state.attributes.current_humidity }}"
|
||||
|
||||
if CONF_ABOVE in config:
|
||||
|
@ -155,8 +155,8 @@ async def async_attach_trigger(
|
|||
if CONF_FOR in config:
|
||||
numeric_state_config[CONF_FOR] = config[CONF_FOR]
|
||||
|
||||
numeric_state_config = numeric_state_automation.TRIGGER_SCHEMA(numeric_state_config)
|
||||
return await numeric_state_automation.async_attach_trigger(
|
||||
numeric_state_config = numeric_state_trigger.TRIGGER_SCHEMA(numeric_state_config)
|
||||
return await numeric_state_trigger.async_attach_trigger(
|
||||
hass, numeric_state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,12 +3,12 @@ from typing import List
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.automation import (
|
||||
AutomationActionType,
|
||||
numeric_state as numeric_state_automation,
|
||||
state as state_automation,
|
||||
)
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.homeassistant.triggers import (
|
||||
numeric_state as numeric_state_trigger,
|
||||
state as state_trigger,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
CONF_ABOVE,
|
||||
|
@ -18,6 +18,7 @@ from homeassistant.const import (
|
|||
CONF_ENTITY_ID,
|
||||
CONF_PLATFORM,
|
||||
CONF_TYPE,
|
||||
CONF_VALUE_TEMPLATE,
|
||||
STATE_CLOSED,
|
||||
STATE_CLOSING,
|
||||
STATE_OPEN,
|
||||
|
@ -182,12 +183,12 @@ async def async_attach_trigger(
|
|||
to_state = STATE_CLOSING
|
||||
|
||||
state_config = {
|
||||
state_automation.CONF_PLATFORM: "state",
|
||||
CONF_PLATFORM: "state",
|
||||
CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state_automation.CONF_TO: to_state,
|
||||
state_trigger.CONF_TO: to_state,
|
||||
}
|
||||
state_config = state_automation.TRIGGER_SCHEMA(state_config)
|
||||
return await state_automation.async_attach_trigger(
|
||||
state_config = state_trigger.TRIGGER_SCHEMA(state_config)
|
||||
return await state_trigger.async_attach_trigger(
|
||||
hass, state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
|
@ -200,13 +201,13 @@ async def async_attach_trigger(
|
|||
value_template = f"{{{{ state.attributes.{position} }}}}"
|
||||
|
||||
numeric_state_config = {
|
||||
numeric_state_automation.CONF_PLATFORM: "numeric_state",
|
||||
numeric_state_automation.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
numeric_state_automation.CONF_BELOW: max_pos,
|
||||
numeric_state_automation.CONF_ABOVE: min_pos,
|
||||
numeric_state_automation.CONF_VALUE_TEMPLATE: value_template,
|
||||
CONF_PLATFORM: "numeric_state",
|
||||
CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
CONF_BELOW: max_pos,
|
||||
CONF_ABOVE: min_pos,
|
||||
CONF_VALUE_TEMPLATE: value_template,
|
||||
}
|
||||
numeric_state_config = numeric_state_automation.TRIGGER_SCHEMA(numeric_state_config)
|
||||
return await numeric_state_automation.async_attach_trigger(
|
||||
numeric_state_config = numeric_state_trigger.TRIGGER_SCHEMA(numeric_state_config)
|
||||
return await numeric_state_trigger.async_attach_trigger(
|
||||
hass, numeric_state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
"""Provides device automations for deconz events."""
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.components.automation.event as event
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.device_automation.exceptions import (
|
||||
InvalidDeviceAutomationConfig,
|
||||
)
|
||||
from homeassistant.components.homeassistant.triggers import event as event_trigger
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_ID,
|
||||
CONF_DOMAIN,
|
||||
|
@ -432,13 +432,13 @@ async def async_attach_trigger(hass, config, action, automation_info):
|
|||
event_id = deconz_event.serial
|
||||
|
||||
event_config = {
|
||||
event.CONF_PLATFORM: "event",
|
||||
event.CONF_EVENT_TYPE: CONF_DECONZ_EVENT,
|
||||
event.CONF_EVENT_DATA: {CONF_UNIQUE_ID: event_id, **trigger},
|
||||
event_trigger.CONF_PLATFORM: "event",
|
||||
event_trigger.CONF_EVENT_TYPE: CONF_DECONZ_EVENT,
|
||||
event_trigger.CONF_EVENT_DATA: {CONF_UNIQUE_ID: event_id, **trigger},
|
||||
}
|
||||
|
||||
event_config = event.TRIGGER_SCHEMA(event_config)
|
||||
return await event.async_attach_trigger(
|
||||
event_config = event_trigger.TRIGGER_SCHEMA(event_config)
|
||||
return await event_trigger.async_attach_trigger(
|
||||
hass, event_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,10 +3,7 @@ from typing import Any, Dict, List
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.automation import (
|
||||
AutomationActionType,
|
||||
state as state_automation,
|
||||
)
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
from homeassistant.components.device_automation.const import (
|
||||
CONF_IS_OFF,
|
||||
CONF_IS_ON,
|
||||
|
@ -16,6 +13,7 @@ from homeassistant.components.device_automation.const import (
|
|||
CONF_TURNED_OFF,
|
||||
CONF_TURNED_ON,
|
||||
)
|
||||
from homeassistant.components.homeassistant.triggers import state as state_trigger
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
CONF_CONDITION,
|
||||
|
@ -157,16 +155,16 @@ async def async_attach_trigger(
|
|||
from_state = "on"
|
||||
to_state = "off"
|
||||
state_config = {
|
||||
state_automation.CONF_PLATFORM: "state",
|
||||
state_automation.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state_automation.CONF_FROM: from_state,
|
||||
state_automation.CONF_TO: to_state,
|
||||
CONF_PLATFORM: "state",
|
||||
state_trigger.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state_trigger.CONF_FROM: from_state,
|
||||
state_trigger.CONF_TO: to_state,
|
||||
}
|
||||
if CONF_FOR in config:
|
||||
state_config[CONF_FOR] = config[CONF_FOR]
|
||||
|
||||
state_config = state_automation.TRIGGER_SCHEMA(state_config)
|
||||
return await state_automation.async_attach_trigger(
|
||||
state_config = state_trigger.TRIGGER_SCHEMA(state_config)
|
||||
return await state_trigger.async_attach_trigger(
|
||||
hass, state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@ from typing import List
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.automation import AutomationActionType, state
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.homeassistant.triggers import state as state_trigger
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_ID,
|
||||
CONF_DOMAIN,
|
||||
|
@ -80,12 +81,12 @@ async def async_attach_trigger(
|
|||
to_state = STATE_OFF
|
||||
|
||||
state_config = {
|
||||
state.CONF_PLATFORM: "state",
|
||||
state_trigger.CONF_PLATFORM: "state",
|
||||
CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state.CONF_FROM: from_state,
|
||||
state.CONF_TO: to_state,
|
||||
state_trigger.CONF_FROM: from_state,
|
||||
state_trigger.CONF_TO: to_state,
|
||||
}
|
||||
state_config = state.TRIGGER_SCHEMA(state_config)
|
||||
return await state.async_attach_trigger(
|
||||
state_config = state_trigger.TRIGGER_SCHEMA(state_config)
|
||||
return await state_trigger.async_attach_trigger(
|
||||
hass, state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
|
23
homeassistant/components/homeassistant/trigger.py
Normal file
23
homeassistant/components/homeassistant/trigger.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
"""Home Assistant trigger dispatcher."""
|
||||
import importlib
|
||||
|
||||
from homeassistant.const import CONF_PLATFORM
|
||||
|
||||
|
||||
def _get_trigger_platform(config):
|
||||
return importlib.import_module(f"..triggers.{config[CONF_PLATFORM]}", __name__)
|
||||
|
||||
|
||||
async def async_validate_trigger_config(hass, config):
|
||||
"""Validate config."""
|
||||
platform = _get_trigger_platform(config)
|
||||
if hasattr(platform, "async_validate_trigger_config"):
|
||||
return await getattr(platform, "async_validate_trigger_config")(hass, config)
|
||||
|
||||
return platform.TRIGGER_SCHEMA(config)
|
||||
|
||||
|
||||
async def async_attach_trigger(hass, config, action, automation_info):
|
||||
"""Attach trigger of specified platform."""
|
||||
platform = _get_trigger_platform(config)
|
||||
return await platform.async_attach_trigger(hass, config, action, automation_info)
|
|
@ -0,0 +1 @@
|
|||
"""Home Assistant triggers."""
|
|
@ -3,11 +3,11 @@ import logging
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.components.automation.event as event
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.device_automation.exceptions import (
|
||||
InvalidDeviceAutomationConfig,
|
||||
)
|
||||
from homeassistant.components.homeassistant.triggers import event as event_trigger
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_ID,
|
||||
CONF_DOMAIN,
|
||||
|
@ -139,13 +139,13 @@ async def async_attach_trigger(hass, config, action, automation_info):
|
|||
trigger = REMOTES[device.model][trigger]
|
||||
|
||||
event_config = {
|
||||
event.CONF_PLATFORM: "event",
|
||||
event.CONF_EVENT_TYPE: CONF_HUE_EVENT,
|
||||
event.CONF_EVENT_DATA: {CONF_UNIQUE_ID: hue_event.unique_id, **trigger},
|
||||
event_trigger.CONF_PLATFORM: "event",
|
||||
event_trigger.CONF_EVENT_TYPE: CONF_HUE_EVENT,
|
||||
event_trigger.CONF_EVENT_DATA: {CONF_UNIQUE_ID: hue_event.unique_id, **trigger},
|
||||
}
|
||||
|
||||
event_config = event.TRIGGER_SCHEMA(event_config)
|
||||
return await event.async_attach_trigger(
|
||||
event_config = event_trigger.TRIGGER_SCHEMA(event_config)
|
||||
return await event_trigger.async_attach_trigger(
|
||||
hass, event_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,14 +3,14 @@ from typing import List
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.automation import (
|
||||
AutomationActionType,
|
||||
numeric_state as numeric_state_automation,
|
||||
)
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
from homeassistant.components.device_automation import (
|
||||
TRIGGER_BASE_SCHEMA,
|
||||
toggle_entity,
|
||||
)
|
||||
from homeassistant.components.homeassistant.triggers import (
|
||||
numeric_state as numeric_state_trigger,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_ABOVE,
|
||||
CONF_BELOW,
|
||||
|
@ -81,9 +81,9 @@ async def async_attach_trigger(
|
|||
|
||||
if trigger_type == "target_humidity_changed":
|
||||
numeric_state_config = {
|
||||
numeric_state_automation.CONF_PLATFORM: "numeric_state",
|
||||
numeric_state_automation.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
numeric_state_automation.CONF_VALUE_TEMPLATE: "{{ state.attributes.humidity }}",
|
||||
numeric_state_trigger.CONF_PLATFORM: "numeric_state",
|
||||
numeric_state_trigger.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
numeric_state_trigger.CONF_VALUE_TEMPLATE: "{{ state.attributes.humidity }}",
|
||||
}
|
||||
|
||||
if CONF_ABOVE in config:
|
||||
|
@ -93,10 +93,10 @@ async def async_attach_trigger(
|
|||
if CONF_FOR in config:
|
||||
numeric_state_config[CONF_FOR] = config[CONF_FOR]
|
||||
|
||||
numeric_state_config = numeric_state_automation.TRIGGER_SCHEMA(
|
||||
numeric_state_config = numeric_state_trigger.TRIGGER_SCHEMA(
|
||||
numeric_state_config
|
||||
)
|
||||
return await numeric_state_automation.async_attach_trigger(
|
||||
return await numeric_state_trigger.async_attach_trigger(
|
||||
hass, numeric_state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
|
|
|
@ -3,8 +3,9 @@ from typing import List
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.automation import AutomationActionType, state
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.homeassistant.triggers import state as state_trigger
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_ID,
|
||||
CONF_DOMAIN,
|
||||
|
@ -80,12 +81,12 @@ async def async_attach_trigger(
|
|||
to_state = STATE_UNLOCKED
|
||||
|
||||
state_config = {
|
||||
state.CONF_PLATFORM: "state",
|
||||
CONF_PLATFORM: "state",
|
||||
CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state.CONF_FROM: from_state,
|
||||
state.CONF_TO: to_state,
|
||||
state_trigger.CONF_FROM: from_state,
|
||||
state_trigger.CONF_TO: to_state,
|
||||
}
|
||||
state_config = state.TRIGGER_SCHEMA(state_config)
|
||||
return await state.async_attach_trigger(
|
||||
state_config = state_trigger.TRIGGER_SCHEMA(state_config)
|
||||
return await state_trigger.async_attach_trigger(
|
||||
hass, state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
|
|
@ -7,7 +7,6 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant.components import mqtt
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
import homeassistant.components.automation.mqtt as automation_mqtt
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_DOMAIN, CONF_PLATFORM, CONF_TYPE
|
||||
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
|
||||
|
@ -27,6 +26,7 @@ from . import (
|
|||
DOMAIN,
|
||||
cleanup_device_registry,
|
||||
debug_info,
|
||||
trigger as mqtt_trigger,
|
||||
)
|
||||
from .discovery import MQTT_DISCOVERY_UPDATED, clear_discovery_hash
|
||||
|
||||
|
@ -83,16 +83,16 @@ class TriggerInstance:
|
|||
async def async_attach_trigger(self):
|
||||
"""Attach MQTT trigger."""
|
||||
mqtt_config = {
|
||||
automation_mqtt.CONF_TOPIC: self.trigger.topic,
|
||||
automation_mqtt.CONF_ENCODING: DEFAULT_ENCODING,
|
||||
automation_mqtt.CONF_QOS: self.trigger.qos,
|
||||
mqtt_trigger.CONF_TOPIC: self.trigger.topic,
|
||||
mqtt_trigger.CONF_ENCODING: DEFAULT_ENCODING,
|
||||
mqtt_trigger.CONF_QOS: self.trigger.qos,
|
||||
}
|
||||
if self.trigger.payload:
|
||||
mqtt_config[CONF_PAYLOAD] = self.trigger.payload
|
||||
|
||||
if self.remove:
|
||||
self.remove()
|
||||
self.remove = await automation_mqtt.async_attach_trigger(
|
||||
self.remove = await mqtt_trigger.async_attach_trigger(
|
||||
self.trigger.hass, mqtt_config, self.action, self.automation_info,
|
||||
)
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
"""Provides device triggers for sensors."""
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.components.automation.numeric_state as numeric_state_automation
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.device_automation.exceptions import (
|
||||
InvalidDeviceAutomationConfig,
|
||||
)
|
||||
from homeassistant.components.homeassistant.triggers import (
|
||||
numeric_state as numeric_state_trigger,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
|
@ -100,18 +102,18 @@ TRIGGER_SCHEMA = vol.All(
|
|||
async def async_attach_trigger(hass, config, action, automation_info):
|
||||
"""Listen for state changes based on configuration."""
|
||||
numeric_state_config = {
|
||||
numeric_state_automation.CONF_PLATFORM: "numeric_state",
|
||||
numeric_state_automation.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
numeric_state_trigger.CONF_PLATFORM: "numeric_state",
|
||||
numeric_state_trigger.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
}
|
||||
if CONF_ABOVE in config:
|
||||
numeric_state_config[numeric_state_automation.CONF_ABOVE] = config[CONF_ABOVE]
|
||||
numeric_state_config[numeric_state_trigger.CONF_ABOVE] = config[CONF_ABOVE]
|
||||
if CONF_BELOW in config:
|
||||
numeric_state_config[numeric_state_automation.CONF_BELOW] = config[CONF_BELOW]
|
||||
numeric_state_config[numeric_state_trigger.CONF_BELOW] = config[CONF_BELOW]
|
||||
if CONF_FOR in config:
|
||||
numeric_state_config[CONF_FOR] = config[CONF_FOR]
|
||||
|
||||
numeric_state_config = numeric_state_automation.TRIGGER_SCHEMA(numeric_state_config)
|
||||
return await numeric_state_automation.async_attach_trigger(
|
||||
numeric_state_config = numeric_state_trigger.TRIGGER_SCHEMA(numeric_state_config)
|
||||
return await numeric_state_trigger.async_attach_trigger(
|
||||
hass, numeric_state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ TRIGGER_SCHEMA = IF_ACTION_SCHEMA = vol.Schema(
|
|||
|
||||
|
||||
async def async_attach_trigger(
|
||||
hass, config, action, automation_info, *, platform_type="numeric_state"
|
||||
hass, config, action, automation_info, *, platform_type="template"
|
||||
):
|
||||
"""Listen for state changes based on configuration."""
|
||||
value_template = config.get(CONF_VALUE_TEMPLATE)
|
|
@ -3,8 +3,9 @@ from typing import List
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.automation import AutomationActionType, state
|
||||
from homeassistant.components.automation import AutomationActionType
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.homeassistant.triggers import state as state_trigger
|
||||
from homeassistant.const import (
|
||||
CONF_DEVICE_ID,
|
||||
CONF_DOMAIN,
|
||||
|
@ -77,12 +78,12 @@ async def async_attach_trigger(
|
|||
to_state = STATE_DOCKED
|
||||
|
||||
state_config = {
|
||||
state.CONF_PLATFORM: "state",
|
||||
CONF_PLATFORM: "state",
|
||||
CONF_ENTITY_ID: config[CONF_ENTITY_ID],
|
||||
state.CONF_FROM: from_state,
|
||||
state.CONF_TO: to_state,
|
||||
state_trigger.CONF_FROM: from_state,
|
||||
state_trigger.CONF_TO: to_state,
|
||||
}
|
||||
state_config = state.TRIGGER_SCHEMA(state_config)
|
||||
return await state.async_attach_trigger(
|
||||
state_config = state_trigger.TRIGGER_SCHEMA(state_config)
|
||||
return await state_trigger.async_attach_trigger(
|
||||
hass, state_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
|
|
@ -9,8 +9,6 @@ from homeassistant.const import CONF_PLATFORM, CONF_WEBHOOK_ID
|
|||
from homeassistant.core import callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from . import DOMAIN as AUTOMATION_DOMAIN
|
||||
|
||||
# mypy: allow-untyped-defs
|
||||
|
||||
DEPENDENCIES = ("webhook",)
|
||||
|
@ -39,7 +37,7 @@ async def async_attach_trigger(hass, config, action, automation_info):
|
|||
"""Trigger based on incoming webhooks."""
|
||||
webhook_id = config.get(CONF_WEBHOOK_ID)
|
||||
hass.components.webhook.async_register(
|
||||
AUTOMATION_DOMAIN,
|
||||
automation_info["domain"],
|
||||
automation_info["name"],
|
||||
webhook_id,
|
||||
partial(_handle_webhook, action),
|
|
@ -1,11 +1,11 @@
|
|||
"""Provides device automations for ZHA devices that emit events."""
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.components.automation.event as event
|
||||
from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
|
||||
from homeassistant.components.device_automation.exceptions import (
|
||||
InvalidDeviceAutomationConfig,
|
||||
)
|
||||
from homeassistant.components.homeassistant.triggers import event as event_trigger
|
||||
from homeassistant.const import CONF_DEVICE_ID, CONF_DOMAIN, CONF_PLATFORM, CONF_TYPE
|
||||
|
||||
from . import DOMAIN
|
||||
|
@ -54,13 +54,13 @@ async def async_attach_trigger(hass, config, action, automation_info):
|
|||
trigger = zha_device.device_automation_triggers[trigger]
|
||||
|
||||
event_config = {
|
||||
event.CONF_PLATFORM: "event",
|
||||
event.CONF_EVENT_TYPE: ZHA_EVENT,
|
||||
event.CONF_EVENT_DATA: {DEVICE_IEEE: str(zha_device.ieee), **trigger},
|
||||
event_trigger.CONF_PLATFORM: "event",
|
||||
event_trigger.CONF_EVENT_TYPE: ZHA_EVENT,
|
||||
event_trigger.CONF_EVENT_DATA: {DEVICE_IEEE: str(zha_device.ieee), **trigger},
|
||||
}
|
||||
|
||||
event_config = event.TRIGGER_SCHEMA(event_config)
|
||||
return await event.async_attach_trigger(
|
||||
event_config = event_trigger.TRIGGER_SCHEMA(event_config)
|
||||
return await event_trigger.async_attach_trigger(
|
||||
hass, event_config, action, automation_info, platform_type="device"
|
||||
)
|
||||
|
||||
|
|
|
@ -995,6 +995,10 @@ CONDITION_SCHEMA: vol.Schema = key_value_schemas(
|
|||
},
|
||||
)
|
||||
|
||||
TRIGGER_SCHEMA = vol.All(
|
||||
ensure_list, [vol.Schema({vol.Required(CONF_PLATFORM): str}, extra=vol.ALLOW_EXTRA)]
|
||||
)
|
||||
|
||||
_SCRIPT_DELAY_SCHEMA = vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_ALIAS): string,
|
||||
|
|
92
homeassistant/helpers/trigger.py
Normal file
92
homeassistant/helpers/trigger.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
"""Triggers."""
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any, Callable, List, Optional
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_PLATFORM
|
||||
from homeassistant.core import CALLBACK_TYPE, callback
|
||||
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||
from homeassistant.loader import IntegrationNotFound, async_get_integration
|
||||
|
||||
_PLATFORM_ALIASES = {
|
||||
"device_automation": ("device",),
|
||||
"homeassistant": ("event", "numeric_state", "state", "time_pattern", "time"),
|
||||
}
|
||||
|
||||
|
||||
async def _async_get_trigger_platform(
|
||||
hass: HomeAssistantType, config: ConfigType
|
||||
) -> Any:
|
||||
platform = config[CONF_PLATFORM]
|
||||
for alias, triggers in _PLATFORM_ALIASES.items():
|
||||
if platform in triggers:
|
||||
platform = alias
|
||||
break
|
||||
try:
|
||||
integration = await async_get_integration(hass, platform)
|
||||
except IntegrationNotFound:
|
||||
raise vol.Invalid(f"Invalid platform '{platform}' specified") from None
|
||||
try:
|
||||
return integration.get_platform("trigger")
|
||||
except ImportError:
|
||||
raise vol.Invalid(
|
||||
f"Integration '{platform}' does not provide trigger support"
|
||||
) from None
|
||||
|
||||
|
||||
async def async_validate_trigger_config(
|
||||
hass: HomeAssistantType, trigger_config: List[ConfigType]
|
||||
) -> List[ConfigType]:
|
||||
"""Validate triggers."""
|
||||
config = []
|
||||
for conf in trigger_config:
|
||||
platform = await _async_get_trigger_platform(hass, conf)
|
||||
if hasattr(platform, "async_validate_trigger_config"):
|
||||
conf = await platform.async_validate_trigger_config(hass, conf)
|
||||
else:
|
||||
conf = platform.TRIGGER_SCHEMA(conf)
|
||||
config.append(conf)
|
||||
return config
|
||||
|
||||
|
||||
async def async_initialize_triggers(
|
||||
hass: HomeAssistantType,
|
||||
trigger_config: List[ConfigType],
|
||||
action: Callable,
|
||||
domain: str,
|
||||
name: str,
|
||||
log_cb: Callable,
|
||||
home_assistant_start: bool = False,
|
||||
) -> Optional[CALLBACK_TYPE]:
|
||||
"""Initialize triggers."""
|
||||
info = {
|
||||
"domain": domain,
|
||||
"name": name,
|
||||
"home_assistant_start": home_assistant_start,
|
||||
}
|
||||
|
||||
triggers = []
|
||||
for conf in trigger_config:
|
||||
platform = await _async_get_trigger_platform(hass, conf)
|
||||
triggers.append(platform.async_attach_trigger(hass, conf, action, info))
|
||||
|
||||
removes = await asyncio.gather(*triggers)
|
||||
|
||||
if None in removes:
|
||||
log_cb(logging.ERROR, "Error setting up trigger")
|
||||
|
||||
removes = list(filter(None, removes))
|
||||
if not removes:
|
||||
return None
|
||||
|
||||
log_cb(logging.INFO, "Initialized trigger")
|
||||
|
||||
@callback
|
||||
def remove_triggers(): # type: ignore
|
||||
"""Remove triggers."""
|
||||
for remove in removes:
|
||||
remove()
|
||||
|
||||
return remove_triggers
|
|
@ -861,6 +861,22 @@ async def test_automation_not_trigger_on_bootstrap(hass):
|
|||
assert ["hello.world"] == calls[0].data.get(ATTR_ENTITY_ID)
|
||||
|
||||
|
||||
async def test_automation_bad_trigger(hass, caplog):
|
||||
"""Test bad trigger configuration."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
automation.DOMAIN,
|
||||
{
|
||||
automation.DOMAIN: {
|
||||
"alias": "hello",
|
||||
"trigger": {"platform": "automation"},
|
||||
"action": [],
|
||||
}
|
||||
},
|
||||
)
|
||||
assert "Integration 'automation' does not provide trigger support." in caplog.text
|
||||
|
||||
|
||||
async def test_automation_with_error_in_script(hass, caplog):
|
||||
"""Test automation with an error in script."""
|
||||
assert await async_setup_component(
|
||||
|
|
1
tests/components/homeassistant/triggers/__init__.py
Normal file
1
tests/components/homeassistant/triggers/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
"""Test core triggers."""
|
|
@ -5,7 +5,9 @@ import pytest
|
|||
import voluptuous as vol
|
||||
|
||||
import homeassistant.components.automation as automation
|
||||
from homeassistant.components.automation import numeric_state
|
||||
from homeassistant.components.homeassistant.triggers import (
|
||||
numeric_state as numeric_state_trigger,
|
||||
)
|
||||
from homeassistant.core import Context
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
@ -776,7 +778,7 @@ async def test_if_fails_setup_bad_for(hass, calls):
|
|||
},
|
||||
)
|
||||
|
||||
with patch.object(automation.numeric_state, "_LOGGER") as mock_logger:
|
||||
with patch.object(numeric_state_trigger, "_LOGGER") as mock_logger:
|
||||
hass.states.async_set("test.entity", 9)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_logger.error.called
|
||||
|
@ -1164,7 +1166,7 @@ async def test_invalid_for_template(hass, calls):
|
|||
},
|
||||
)
|
||||
|
||||
with patch.object(automation.numeric_state, "_LOGGER") as mock_logger:
|
||||
with patch.object(numeric_state_trigger, "_LOGGER") as mock_logger:
|
||||
hass.states.async_set("test.entity", 9)
|
||||
await hass.async_block_till_done()
|
||||
assert mock_logger.error.called
|
||||
|
@ -1234,6 +1236,6 @@ async def test_if_fires_on_entities_change_overlap_for_template(hass, calls):
|
|||
def test_below_above():
|
||||
"""Test above cannot be above below."""
|
||||
with pytest.raises(vol.Invalid):
|
||||
numeric_state.TRIGGER_SCHEMA(
|
||||
numeric_state_trigger.TRIGGER_SCHEMA(
|
||||
{"platform": "numeric_state", "above": 1200, "below": 1000}
|
||||
)
|
|
@ -4,6 +4,7 @@ from datetime import timedelta
|
|||
import pytest
|
||||
|
||||
import homeassistant.components.automation as automation
|
||||
from homeassistant.components.homeassistant.triggers import state as state_trigger
|
||||
from homeassistant.core import Context
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
@ -327,7 +328,7 @@ async def test_if_fails_setup_bad_for(hass, calls):
|
|||
},
|
||||
)
|
||||
|
||||
with patch.object(automation.state, "_LOGGER") as mock_logger:
|
||||
with patch.object(state_trigger, "_LOGGER") as mock_logger:
|
||||
hass.states.async_set("test.entity", "world")
|
||||
await hass.async_block_till_done()
|
||||
assert mock_logger.error.called
|
||||
|
@ -942,7 +943,7 @@ async def test_invalid_for_template_1(hass, calls):
|
|||
},
|
||||
)
|
||||
|
||||
with patch.object(automation.state, "_LOGGER") as mock_logger:
|
||||
with patch.object(state_trigger, "_LOGGER") as mock_logger:
|
||||
hass.states.async_set("test.entity", "world")
|
||||
await hass.async_block_till_done()
|
||||
assert mock_logger.error.called
|
|
@ -361,7 +361,7 @@ async def test_untrack_time_change(hass):
|
|||
"""Test for removing tracked time changes."""
|
||||
mock_track_time_change = Mock()
|
||||
with patch(
|
||||
"homeassistant.components.automation.time.async_track_time_change",
|
||||
"homeassistant.components.homeassistant.triggers.time.async_track_time_change",
|
||||
return_value=mock_track_time_change,
|
||||
):
|
||||
assert await async_setup_component(
|
|
@ -419,6 +419,8 @@ async def test_missing_discover_abbreviations(hass, mqtt_mock, caplog):
|
|||
missing = []
|
||||
regex = re.compile(r"(CONF_[a-zA-Z\d_]*) *= *[\'\"]([a-zA-Z\d_]*)[\'\"]")
|
||||
for fil in Path(mqtt.__file__).parent.rglob("*.py"):
|
||||
if fil.name == "trigger.py":
|
||||
continue
|
||||
with open(fil) as file:
|
||||
matches = re.findall(regex, file.read())
|
||||
for match in matches:
|
||||
|
|
|
@ -5,6 +5,7 @@ from unittest import mock
|
|||
import pytest
|
||||
|
||||
import homeassistant.components.automation as automation
|
||||
from homeassistant.components.template import trigger as template_trigger
|
||||
from homeassistant.core import Context, callback
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
@ -782,7 +783,7 @@ async def test_invalid_for_template_1(hass, calls):
|
|||
},
|
||||
)
|
||||
|
||||
with mock.patch.object(automation.template, "_LOGGER") as mock_logger:
|
||||
with mock.patch.object(template_trigger, "_LOGGER") as mock_logger:
|
||||
hass.states.async_set("test.entity", "world")
|
||||
await hass.async_block_till_done()
|
||||
assert mock_logger.error.called
|
12
tests/helpers/test_trigger.py
Normal file
12
tests/helpers/test_trigger.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
"""The tests for the trigger helper."""
|
||||
import pytest
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.helpers.trigger import async_validate_trigger_config
|
||||
|
||||
|
||||
async def test_bad_trigger_platform(hass):
|
||||
"""Test bad trigger platform."""
|
||||
with pytest.raises(vol.Invalid) as ex:
|
||||
await async_validate_trigger_config(hass, [{"platform": "not_a_platform"}])
|
||||
assert "Invalid platform 'not_a_platform' specified" in str(ex)
|
Loading…
Add table
Reference in a new issue