diff --git a/homeassistant/components/automation/numeric_state.py b/homeassistant/components/automation/numeric_state.py
index 8d88fe9cae6..0c8ab3d9c8b 100644
--- a/homeassistant/components/automation/numeric_state.py
+++ b/homeassistant/components/automation/numeric_state.py
@@ -4,7 +4,7 @@ import logging
 import voluptuous as vol
 
 from homeassistant import exceptions
-from homeassistant.core import callback
+from homeassistant.core import CALLBACK_TYPE, callback
 from homeassistant.const import (
     CONF_VALUE_TEMPLATE,
     CONF_PLATFORM,
@@ -17,7 +17,8 @@ from homeassistant.helpers.event import async_track_state_change, async_track_sa
 from homeassistant.helpers import condition, config_validation as cv, template
 
 
-# mypy: allow-untyped-defs, no-check-untyped-defs
+# mypy: allow-incomplete-defs, allow-untyped-calls, allow-untyped-defs
+# mypy: no-check-untyped-defs
 
 TRIGGER_SCHEMA = vol.All(
     vol.Schema(
@@ -42,7 +43,7 @@ _LOGGER = logging.getLogger(__name__)
 
 async def async_attach_trigger(
     hass, config, action, automation_info, *, platform_type="numeric_state"
-):
+) -> CALLBACK_TYPE:
     """Listen for state changes based on configuration."""
     entity_id = config.get(CONF_ENTITY_ID)
     below = config.get(CONF_BELOW)
@@ -52,7 +53,7 @@ async def async_attach_trigger(
     value_template = config.get(CONF_VALUE_TEMPLATE)
     unsub_track_same = {}
     entities_triggered = set()
-    period = {}
+    period: dict = {}
 
     if value_template is not None:
         value_template.hass = hass
diff --git a/homeassistant/components/cover/device_trigger.py b/homeassistant/components/cover/device_trigger.py
new file mode 100644
index 00000000000..4f256a87dc5
--- /dev/null
+++ b/homeassistant/components/cover/device_trigger.py
@@ -0,0 +1,210 @@
+"""Provides device automations for Cover."""
+from typing import List
+import voluptuous as vol
+
+from homeassistant.const import (
+    ATTR_SUPPORTED_FEATURES,
+    CONF_ABOVE,
+    CONF_BELOW,
+    CONF_DOMAIN,
+    CONF_TYPE,
+    CONF_PLATFORM,
+    CONF_DEVICE_ID,
+    CONF_ENTITY_ID,
+    STATE_CLOSED,
+    STATE_CLOSING,
+    STATE_OPEN,
+    STATE_OPENING,
+)
+from homeassistant.core import HomeAssistant, CALLBACK_TYPE
+from homeassistant.helpers import config_validation as cv, entity_registry
+from homeassistant.helpers.typing import ConfigType
+from homeassistant.components.automation import (
+    state as state_automation,
+    numeric_state as numeric_state_automation,
+    AutomationActionType,
+)
+from homeassistant.components.device_automation import TRIGGER_BASE_SCHEMA
+from . import (
+    DOMAIN,
+    SUPPORT_CLOSE,
+    SUPPORT_OPEN,
+    SUPPORT_SET_POSITION,
+    SUPPORT_SET_TILT_POSITION,
+)
+
+POSITION_TRIGGER_TYPES = {"position", "tilt_position"}
+STATE_TRIGGER_TYPES = {"opened", "closed", "opening", "closing"}
+
+POSITION_TRIGGER_SCHEMA = vol.All(
+    TRIGGER_BASE_SCHEMA.extend(
+        {
+            vol.Required(CONF_ENTITY_ID): cv.entity_id,
+            vol.Required(CONF_TYPE): vol.In(POSITION_TRIGGER_TYPES),
+            vol.Optional(CONF_ABOVE): vol.All(
+                vol.Coerce(int), vol.Range(min=0, max=100)
+            ),
+            vol.Optional(CONF_BELOW): vol.All(
+                vol.Coerce(int), vol.Range(min=0, max=100)
+            ),
+        }
+    ),
+    cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE),
+)
+
+STATE_TRIGGER_SCHEMA = TRIGGER_BASE_SCHEMA.extend(
+    {
+        vol.Required(CONF_ENTITY_ID): cv.entity_id,
+        vol.Required(CONF_TYPE): vol.In(STATE_TRIGGER_TYPES),
+    }
+)
+
+TRIGGER_SCHEMA = vol.Any(POSITION_TRIGGER_SCHEMA, STATE_TRIGGER_SCHEMA)
+
+
+async def async_get_triggers(hass: HomeAssistant, device_id: str) -> List[dict]:
+    """List device triggers for Cover devices."""
+    registry = await entity_registry.async_get_registry(hass)
+    triggers = []
+
+    # Get all the integrations entities for this device
+    for entry in entity_registry.async_entries_for_device(registry, device_id):
+        if entry.domain != DOMAIN:
+            continue
+
+        state = hass.states.get(entry.entity_id)
+        if not state or ATTR_SUPPORTED_FEATURES not in state.attributes:
+            continue
+
+        supported_features = state.attributes[ATTR_SUPPORTED_FEATURES]
+        supports_open_close = supported_features & (SUPPORT_OPEN | SUPPORT_CLOSE)
+
+        # Add triggers for each entity that belongs to this integration
+        if supports_open_close:
+            triggers.append(
+                {
+                    CONF_PLATFORM: "device",
+                    CONF_DEVICE_ID: device_id,
+                    CONF_DOMAIN: DOMAIN,
+                    CONF_ENTITY_ID: entry.entity_id,
+                    CONF_TYPE: "opened",
+                }
+            )
+            triggers.append(
+                {
+                    CONF_PLATFORM: "device",
+                    CONF_DEVICE_ID: device_id,
+                    CONF_DOMAIN: DOMAIN,
+                    CONF_ENTITY_ID: entry.entity_id,
+                    CONF_TYPE: "closed",
+                }
+            )
+            triggers.append(
+                {
+                    CONF_PLATFORM: "device",
+                    CONF_DEVICE_ID: device_id,
+                    CONF_DOMAIN: DOMAIN,
+                    CONF_ENTITY_ID: entry.entity_id,
+                    CONF_TYPE: "opening",
+                }
+            )
+            triggers.append(
+                {
+                    CONF_PLATFORM: "device",
+                    CONF_DEVICE_ID: device_id,
+                    CONF_DOMAIN: DOMAIN,
+                    CONF_ENTITY_ID: entry.entity_id,
+                    CONF_TYPE: "closing",
+                }
+            )
+        if supported_features & SUPPORT_SET_POSITION:
+            triggers.append(
+                {
+                    CONF_PLATFORM: "device",
+                    CONF_DEVICE_ID: device_id,
+                    CONF_DOMAIN: DOMAIN,
+                    CONF_ENTITY_ID: entry.entity_id,
+                    CONF_TYPE: "position",
+                }
+            )
+        if supported_features & SUPPORT_SET_TILT_POSITION:
+            triggers.append(
+                {
+                    CONF_PLATFORM: "device",
+                    CONF_DEVICE_ID: device_id,
+                    CONF_DOMAIN: DOMAIN,
+                    CONF_ENTITY_ID: entry.entity_id,
+                    CONF_TYPE: "tilt_position",
+                }
+            )
+
+    return triggers
+
+
+async def async_get_trigger_capabilities(hass: HomeAssistant, config: dict) -> dict:
+    """List trigger capabilities."""
+    if config[CONF_TYPE] not in ["position", "tilt_position"]:
+        return {}
+
+    return {
+        "extra_fields": vol.Schema(
+            {
+                vol.Optional(CONF_ABOVE, default=0): vol.All(
+                    vol.Coerce(int), vol.Range(min=0, max=100)
+                ),
+                vol.Optional(CONF_BELOW, default=100): vol.All(
+                    vol.Coerce(int), vol.Range(min=0, max=100)
+                ),
+            }
+        )
+    }
+
+
+async def async_attach_trigger(
+    hass: HomeAssistant,
+    config: ConfigType,
+    action: AutomationActionType,
+    automation_info: dict,
+) -> CALLBACK_TYPE:
+    """Attach a trigger."""
+    config = TRIGGER_SCHEMA(config)
+
+    if config[CONF_TYPE] in STATE_TRIGGER_TYPES:
+        if config[CONF_TYPE] == "opened":
+            to_state = STATE_OPEN
+        elif config[CONF_TYPE] == "closed":
+            to_state = STATE_CLOSED
+        elif config[CONF_TYPE] == "opening":
+            to_state = STATE_OPENING
+        elif config[CONF_TYPE] == "closing":
+            to_state = STATE_CLOSING
+
+        state_config = {
+            state_automation.CONF_PLATFORM: "state",
+            CONF_ENTITY_ID: config[CONF_ENTITY_ID],
+            state_automation.CONF_TO: to_state,
+        }
+        state_config = state_automation.TRIGGER_SCHEMA(state_config)
+        return await state_automation.async_attach_trigger(
+            hass, state_config, action, automation_info, platform_type="device"
+        )
+
+    if config[CONF_TYPE] == "position":
+        position = "current_position"
+    if config[CONF_TYPE] == "tilt_position":
+        position = "current_tilt_position"
+    min_pos = config.get(CONF_ABOVE, -1)
+    max_pos = config.get(CONF_BELOW, 101)
+    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,
+    }
+    numeric_state_config = numeric_state_automation.TRIGGER_SCHEMA(numeric_state_config)
+    return await numeric_state_automation.async_attach_trigger(
+        hass, numeric_state_config, action, automation_info, platform_type="device"
+    )
diff --git a/homeassistant/components/cover/strings.json b/homeassistant/components/cover/strings.json
index e4c72746ee4..36492cc5ed5 100644
--- a/homeassistant/components/cover/strings.json
+++ b/homeassistant/components/cover/strings.json
@@ -1,12 +1,20 @@
 {
-    "device_automation": {
-        "condition_type": {
-            "is_open": "{entity_name} is open",
-            "is_closed": "{entity_name} is closed",
-            "is_opening": "{entity_name} is opening",
-            "is_closing": "{entity_name} is closing",
-            "is_position": "{entity_name} position is",
-            "is_tilt_position": "{entity_name} tilt position is"
-        }
+  "device_automation": {
+    "condition_type": {
+      "is_open": "{entity_name} is open",
+      "is_closed": "{entity_name} is closed",
+      "is_opening": "{entity_name} is opening",
+      "is_closing": "{entity_name} is closing",
+      "is_position": "Current {entity_name} position is",
+      "is_tilt_position": "Current {entity_name} tilt position is"
+    },
+    "trigger_type": {
+      "opened": "{entity_name} opened",
+      "closed": "{entity_name} closed",
+      "opening": "{entity_name} opening",
+      "closing": "{entity_name} closing",
+      "position": "{entity_name} position changes",
+      "tilt_position": "{entity_name} tilt position changes"
     }
-}
\ No newline at end of file
+  }
+}
diff --git a/tests/components/cover/test_device_trigger.py b/tests/components/cover/test_device_trigger.py
new file mode 100644
index 00000000000..4f50c0639c0
--- /dev/null
+++ b/tests/components/cover/test_device_trigger.py
@@ -0,0 +1,702 @@
+"""The tests for Cover device triggers."""
+import pytest
+
+from homeassistant.components.cover import DOMAIN
+from homeassistant.const import (
+    CONF_PLATFORM,
+    STATE_CLOSED,
+    STATE_CLOSING,
+    STATE_OPEN,
+    STATE_OPENING,
+)
+from homeassistant.setup import async_setup_component
+import homeassistant.components.automation as automation
+from homeassistant.helpers import device_registry
+
+from tests.common import (
+    MockConfigEntry,
+    assert_lists_same,
+    async_mock_service,
+    mock_device_registry,
+    mock_registry,
+    async_get_device_automations,
+    async_get_device_automation_capabilities,
+)
+
+
+@pytest.fixture
+def device_reg(hass):
+    """Return an empty, loaded, registry."""
+    return mock_device_registry(hass)
+
+
+@pytest.fixture
+def entity_reg(hass):
+    """Return an empty, loaded, registry."""
+    return mock_registry(hass)
+
+
+@pytest.fixture
+def calls(hass):
+    """Track calls to a mock serivce."""
+    return async_mock_service(hass, "test", "automation")
+
+
+async def test_get_triggers(hass, device_reg, entity_reg):
+    """Test we get the expected triggers from a cover."""
+    platform = getattr(hass.components, f"test.{DOMAIN}")
+    platform.init()
+    ent = platform.ENTITIES[0]
+
+    config_entry = MockConfigEntry(domain="test", data={})
+    config_entry.add_to_hass(hass)
+    device_entry = device_reg.async_get_or_create(
+        config_entry_id=config_entry.entry_id,
+        connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
+    )
+    entity_reg.async_get_or_create(
+        DOMAIN, "test", ent.unique_id, device_id=device_entry.id
+    )
+    assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
+
+    expected_triggers = [
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "opened",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "closed",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "opening",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "closing",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+    ]
+    triggers = await async_get_device_automations(hass, "trigger", device_entry.id)
+    assert_lists_same(triggers, expected_triggers)
+
+
+async def test_get_triggers_set_pos(hass, device_reg, entity_reg):
+    """Test we get the expected triggers from a cover."""
+    platform = getattr(hass.components, f"test.{DOMAIN}")
+    platform.init()
+    ent = platform.ENTITIES[1]
+
+    config_entry = MockConfigEntry(domain="test", data={})
+    config_entry.add_to_hass(hass)
+    device_entry = device_reg.async_get_or_create(
+        config_entry_id=config_entry.entry_id,
+        connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
+    )
+    entity_reg.async_get_or_create(
+        DOMAIN, "test", ent.unique_id, device_id=device_entry.id
+    )
+    assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
+
+    expected_triggers = [
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "opened",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "closed",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "opening",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "closing",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "position",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+    ]
+    triggers = await async_get_device_automations(hass, "trigger", device_entry.id)
+    assert_lists_same(triggers, expected_triggers)
+
+
+async def test_get_triggers_set_tilt_pos(hass, device_reg, entity_reg):
+    """Test we get the expected triggers from a cover."""
+    platform = getattr(hass.components, f"test.{DOMAIN}")
+    platform.init()
+    ent = platform.ENTITIES[2]
+
+    config_entry = MockConfigEntry(domain="test", data={})
+    config_entry.add_to_hass(hass)
+    device_entry = device_reg.async_get_or_create(
+        config_entry_id=config_entry.entry_id,
+        connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
+    )
+    entity_reg.async_get_or_create(
+        DOMAIN, "test", ent.unique_id, device_id=device_entry.id
+    )
+    assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
+
+    expected_triggers = [
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "opened",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "closed",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "opening",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "closing",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+        {
+            "platform": "device",
+            "domain": DOMAIN,
+            "type": "tilt_position",
+            "device_id": device_entry.id,
+            "entity_id": f"{DOMAIN}.test_{ent.unique_id}",
+        },
+    ]
+    triggers = await async_get_device_automations(hass, "trigger", device_entry.id)
+    assert_lists_same(triggers, expected_triggers)
+
+
+async def test_get_trigger_capabilities(hass, device_reg, entity_reg):
+    """Test we get the expected capabilities from a cover trigger."""
+    platform = getattr(hass.components, f"test.{DOMAIN}")
+    platform.init()
+    ent = platform.ENTITIES[0]
+
+    config_entry = MockConfigEntry(domain="test", data={})
+    config_entry.add_to_hass(hass)
+    device_entry = device_reg.async_get_or_create(
+        config_entry_id=config_entry.entry_id,
+        connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
+    )
+    entity_reg.async_get_or_create(
+        DOMAIN, "test", ent.unique_id, device_id=device_entry.id
+    )
+
+    assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
+
+    triggers = await async_get_device_automations(hass, "trigger", device_entry.id)
+    assert len(triggers) == 4
+    for trigger in triggers:
+        capabilities = await async_get_device_automation_capabilities(
+            hass, "trigger", trigger
+        )
+        assert capabilities == {"extra_fields": []}
+
+
+async def test_get_trigger_capabilities_set_pos(hass, device_reg, entity_reg):
+    """Test we get the expected capabilities from a cover trigger."""
+    platform = getattr(hass.components, f"test.{DOMAIN}")
+    platform.init()
+    ent = platform.ENTITIES[1]
+
+    config_entry = MockConfigEntry(domain="test", data={})
+    config_entry.add_to_hass(hass)
+    device_entry = device_reg.async_get_or_create(
+        config_entry_id=config_entry.entry_id,
+        connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
+    )
+    entity_reg.async_get_or_create(
+        DOMAIN, "test", ent.unique_id, device_id=device_entry.id
+    )
+
+    assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
+
+    expected_capabilities = {
+        "extra_fields": [
+            {
+                "name": "above",
+                "optional": True,
+                "type": "integer",
+                "default": 0,
+                "valueMax": 100,
+                "valueMin": 0,
+            },
+            {
+                "name": "below",
+                "optional": True,
+                "type": "integer",
+                "default": 100,
+                "valueMax": 100,
+                "valueMin": 0,
+            },
+        ]
+    }
+    triggers = await async_get_device_automations(hass, "trigger", device_entry.id)
+    assert len(triggers) == 5
+    for trigger in triggers:
+        capabilities = await async_get_device_automation_capabilities(
+            hass, "trigger", trigger
+        )
+        if trigger["type"] == "position":
+            assert capabilities == expected_capabilities
+        else:
+            assert capabilities == {"extra_fields": []}
+
+
+async def test_get_trigger_capabilities_set_tilt_pos(hass, device_reg, entity_reg):
+    """Test we get the expected capabilities from a cover trigger."""
+    platform = getattr(hass.components, f"test.{DOMAIN}")
+    platform.init()
+    ent = platform.ENTITIES[2]
+
+    config_entry = MockConfigEntry(domain="test", data={})
+    config_entry.add_to_hass(hass)
+    device_entry = device_reg.async_get_or_create(
+        config_entry_id=config_entry.entry_id,
+        connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
+    )
+    entity_reg.async_get_or_create(
+        DOMAIN, "test", ent.unique_id, device_id=device_entry.id
+    )
+
+    assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
+
+    expected_capabilities = {
+        "extra_fields": [
+            {
+                "name": "above",
+                "optional": True,
+                "type": "integer",
+                "default": 0,
+                "valueMax": 100,
+                "valueMin": 0,
+            },
+            {
+                "name": "below",
+                "optional": True,
+                "type": "integer",
+                "default": 100,
+                "valueMax": 100,
+                "valueMin": 0,
+            },
+        ]
+    }
+    triggers = await async_get_device_automations(hass, "trigger", device_entry.id)
+    assert len(triggers) == 5
+    for trigger in triggers:
+        capabilities = await async_get_device_automation_capabilities(
+            hass, "trigger", trigger
+        )
+        if trigger["type"] == "tilt_position":
+            assert capabilities == expected_capabilities
+        else:
+            assert capabilities == {"extra_fields": []}
+
+
+async def test_if_fires_on_state_change(hass, calls):
+    """Test for state triggers firing."""
+    hass.states.async_set("cover.entity", STATE_CLOSED)
+
+    assert await async_setup_component(
+        hass,
+        automation.DOMAIN,
+        {
+            automation.DOMAIN: [
+                {
+                    "trigger": {
+                        "platform": "device",
+                        "domain": DOMAIN,
+                        "device_id": "",
+                        "entity_id": "cover.entity",
+                        "type": "opened",
+                    },
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "opened - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+                {
+                    "trigger": {
+                        "platform": "device",
+                        "domain": DOMAIN,
+                        "device_id": "",
+                        "entity_id": "cover.entity",
+                        "type": "closed",
+                    },
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "closed - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+                {
+                    "trigger": {
+                        "platform": "device",
+                        "domain": DOMAIN,
+                        "device_id": "",
+                        "entity_id": "cover.entity",
+                        "type": "opening",
+                    },
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "opening - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+                {
+                    "trigger": {
+                        "platform": "device",
+                        "domain": DOMAIN,
+                        "device_id": "",
+                        "entity_id": "cover.entity",
+                        "type": "closing",
+                    },
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "closing - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+            ]
+        },
+    )
+
+    # Fake that the entity is opened.
+    hass.states.async_set("cover.entity", STATE_OPEN)
+    await hass.async_block_till_done()
+    assert len(calls) == 1
+    assert calls[0].data[
+        "some"
+    ] == "opened - device - {} - closed - open - None".format("cover.entity")
+
+    # Fake that the entity is closed.
+    hass.states.async_set("cover.entity", STATE_CLOSED)
+    await hass.async_block_till_done()
+    assert len(calls) == 2
+    assert calls[1].data[
+        "some"
+    ] == "closed - device - {} - open - closed - None".format("cover.entity")
+
+    # Fake that the entity is opening.
+    hass.states.async_set("cover.entity", STATE_OPENING)
+    await hass.async_block_till_done()
+    assert len(calls) == 3
+    assert calls[2].data[
+        "some"
+    ] == "opening - device - {} - closed - opening - None".format("cover.entity")
+
+    # Fake that the entity is closing.
+    hass.states.async_set("cover.entity", STATE_CLOSING)
+    await hass.async_block_till_done()
+    assert len(calls) == 4
+    assert calls[3].data[
+        "some"
+    ] == "closing - device - {} - opening - closing - None".format("cover.entity")
+
+
+async def test_if_fires_on_position(hass, calls):
+    """Test for position triggers."""
+    platform = getattr(hass.components, f"test.{DOMAIN}")
+    platform.init()
+    ent = platform.ENTITIES[1]
+    assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
+
+    assert await async_setup_component(
+        hass,
+        automation.DOMAIN,
+        {
+            automation.DOMAIN: [
+                {
+                    "trigger": [
+                        {
+                            "platform": "device",
+                            "domain": DOMAIN,
+                            "device_id": "",
+                            "entity_id": ent.entity_id,
+                            "type": "position",
+                            "above": 45,
+                        }
+                    ],
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "is_pos_gt_45 - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+                {
+                    "trigger": [
+                        {
+                            "platform": "device",
+                            "domain": DOMAIN,
+                            "device_id": "",
+                            "entity_id": ent.entity_id,
+                            "type": "position",
+                            "below": 90,
+                        }
+                    ],
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "is_pos_lt_90 - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+                {
+                    "trigger": [
+                        {
+                            "platform": "device",
+                            "domain": DOMAIN,
+                            "device_id": "",
+                            "entity_id": ent.entity_id,
+                            "type": "position",
+                            "above": 45,
+                            "below": 90,
+                        }
+                    ],
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "is_pos_gt_45_lt_90 - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+            ]
+        },
+    )
+    hass.states.async_set(
+        ent.entity_id, STATE_CLOSED, attributes={"current_position": 50}
+    )
+    await hass.async_block_till_done()
+    assert len(calls) == 3
+    assert sorted(
+        [calls[0].data["some"], calls[1].data["some"], calls[2].data["some"]]
+    ) == sorted(
+        [
+            "is_pos_gt_45_lt_90 - device - cover.set_position_cover - open - closed - None",
+            "is_pos_lt_90 - device - cover.set_position_cover - open - closed - None",
+            "is_pos_gt_45 - device - cover.set_position_cover - open - closed - None",
+        ]
+    )
+
+    hass.states.async_set(
+        ent.entity_id, STATE_CLOSED, attributes={"current_position": 95}
+    )
+    await hass.async_block_till_done()
+    hass.states.async_set(
+        ent.entity_id, STATE_CLOSED, attributes={"current_position": 45}
+    )
+    await hass.async_block_till_done()
+    assert len(calls) == 4
+    assert (
+        calls[3].data["some"]
+        == "is_pos_lt_90 - device - cover.set_position_cover - closed - closed - None"
+    )
+
+    hass.states.async_set(
+        ent.entity_id, STATE_CLOSED, attributes={"current_position": 90}
+    )
+    await hass.async_block_till_done()
+    assert len(calls) == 5
+    assert (
+        calls[4].data["some"]
+        == "is_pos_gt_45 - device - cover.set_position_cover - closed - closed - None"
+    )
+
+
+async def test_if_fires_on_tilt_position(hass, calls):
+    """Test for tilt position triggers."""
+    platform = getattr(hass.components, f"test.{DOMAIN}")
+    platform.init()
+    ent = platform.ENTITIES[1]
+    assert await async_setup_component(hass, DOMAIN, {DOMAIN: {CONF_PLATFORM: "test"}})
+
+    assert await async_setup_component(
+        hass,
+        automation.DOMAIN,
+        {
+            automation.DOMAIN: [
+                {
+                    "trigger": [
+                        {
+                            "platform": "device",
+                            "domain": DOMAIN,
+                            "device_id": "",
+                            "entity_id": ent.entity_id,
+                            "type": "tilt_position",
+                            "above": 45,
+                        }
+                    ],
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "is_pos_gt_45 - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+                {
+                    "trigger": [
+                        {
+                            "platform": "device",
+                            "domain": DOMAIN,
+                            "device_id": "",
+                            "entity_id": ent.entity_id,
+                            "type": "tilt_position",
+                            "below": 90,
+                        }
+                    ],
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "is_pos_lt_90 - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+                {
+                    "trigger": [
+                        {
+                            "platform": "device",
+                            "domain": DOMAIN,
+                            "device_id": "",
+                            "entity_id": ent.entity_id,
+                            "type": "tilt_position",
+                            "above": 45,
+                            "below": 90,
+                        }
+                    ],
+                    "action": {
+                        "service": "test.automation",
+                        "data_template": {
+                            "some": (
+                                "is_pos_gt_45_lt_90 - {{ trigger.platform}} - "
+                                "{{ trigger.entity_id}} - {{ trigger.from_state.state}} - "
+                                "{{ trigger.to_state.state}} - {{ trigger.for }}"
+                            )
+                        },
+                    },
+                },
+            ]
+        },
+    )
+    hass.states.async_set(
+        ent.entity_id, STATE_CLOSED, attributes={"current_tilt_position": 50}
+    )
+    await hass.async_block_till_done()
+    assert len(calls) == 3
+    assert sorted(
+        [calls[0].data["some"], calls[1].data["some"], calls[2].data["some"]]
+    ) == sorted(
+        [
+            "is_pos_gt_45_lt_90 - device - cover.set_position_cover - open - closed - None",
+            "is_pos_lt_90 - device - cover.set_position_cover - open - closed - None",
+            "is_pos_gt_45 - device - cover.set_position_cover - open - closed - None",
+        ]
+    )
+
+    hass.states.async_set(
+        ent.entity_id, STATE_CLOSED, attributes={"current_tilt_position": 95}
+    )
+    await hass.async_block_till_done()
+    hass.states.async_set(
+        ent.entity_id, STATE_CLOSED, attributes={"current_tilt_position": 45}
+    )
+    await hass.async_block_till_done()
+    assert len(calls) == 4
+    assert (
+        calls[3].data["some"]
+        == "is_pos_lt_90 - device - cover.set_position_cover - closed - closed - None"
+    )
+
+    hass.states.async_set(
+        ent.entity_id, STATE_CLOSED, attributes={"current_tilt_position": 90}
+    )
+    await hass.async_block_till_done()
+    assert len(calls) == 5
+    assert (
+        calls[4].data["some"]
+        == "is_pos_gt_45 - device - cover.set_position_cover - closed - closed - None"
+    )