mirror of
https://github.com/home-assistant/core.git
synced 2026-09-25 17:04:04 -04:00
Homee: Exclude covers, that don't provide a closed state. (#172476)
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""The homee cover platform."""
|
||||
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from pyHomee.const import AttributeType, NodeProfile
|
||||
from pyHomee.model import HomeeAttribute, HomeeNode
|
||||
@@ -35,6 +35,12 @@ COVER_DEVICE_PROFILES = {
|
||||
NodeProfile.ENTRANCE_GATE_OPERATOR: CoverDeviceClass.GATE,
|
||||
NodeProfile.SHUTTER_POSITION_SWITCH: CoverDeviceClass.SHUTTER,
|
||||
}
|
||||
IS_CLOSED_ATTRIBUTES = [
|
||||
AttributeType.OPEN_CLOSE,
|
||||
AttributeType.UP_DOWN,
|
||||
AttributeType.POSITION,
|
||||
AttributeType.SHUTTER_SLAT_POSITION,
|
||||
]
|
||||
|
||||
|
||||
def get_open_close_attribute(node: HomeeNode) -> HomeeAttribute | None:
|
||||
@@ -83,9 +89,23 @@ async def add_cover_entities(
|
||||
nodes: list[HomeeNode],
|
||||
) -> None:
|
||||
"""Add homee cover entities."""
|
||||
async_add_entities(
|
||||
HomeeCover(node, config_entry) for node in nodes if is_cover_node(node)
|
||||
)
|
||||
entities: list[HomeeNode] = []
|
||||
for node in nodes:
|
||||
if is_cover_node(node):
|
||||
if any(
|
||||
node.get_attribute_by_type(attr) is not None
|
||||
for attr in IS_CLOSED_ATTRIBUTES
|
||||
):
|
||||
entities.append(node)
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"Cover %s could not be added, because it is missing an Attribute "
|
||||
"for closed indication. Please open an issue at "
|
||||
"https://github.com/home-assistant/core/issues",
|
||||
node.name,
|
||||
)
|
||||
|
||||
async_add_entities(HomeeCover(cover, config_entry) for cover in entities)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@@ -187,7 +207,7 @@ class HomeeCover(HomeeNodeEntity, CoverEntity):
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_closed(self) -> bool | None:
|
||||
def is_closed(self) -> bool:
|
||||
"""Return if the cover is closed."""
|
||||
if (
|
||||
attribute := self._node.get_attribute_by_type(AttributeType.POSITION)
|
||||
@@ -200,15 +220,16 @@ class HomeeCover(HomeeNodeEntity, CoverEntity):
|
||||
|
||||
return self._open_close_attribute.get_value() == 0
|
||||
|
||||
# If none of the above is present, it might be a slat only cover.
|
||||
if (
|
||||
attribute := self._node.get_attribute_by_type(
|
||||
AttributeType.SHUTTER_SLAT_POSITION
|
||||
)
|
||||
) is not None:
|
||||
return attribute.get_value() == attribute.minimum
|
||||
# If none of the above is present, it will be a slat only cover.
|
||||
attribute = self._node.get_attribute_by_type(
|
||||
AttributeType.SHUTTER_SLAT_POSITION
|
||||
)
|
||||
if TYPE_CHECKING:
|
||||
# This case should not happen, because we check for
|
||||
# the presence of an IS_CLOSED_ATTRIBUTE when adding entities.
|
||||
assert attribute is not None
|
||||
|
||||
return None
|
||||
return attribute.get_value() == attribute.minimum
|
||||
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
"""Open the cover."""
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"id": 4,
|
||||
"name": "Invalid Cover",
|
||||
"profile": 2002,
|
||||
"image": "default",
|
||||
"favorite": 0,
|
||||
"order": 1,
|
||||
"protocol": 23,
|
||||
"routing": 0,
|
||||
"state": 1,
|
||||
"state_changed": 1676901608,
|
||||
"added": 1672148537,
|
||||
"history": 1,
|
||||
"cube_type": 14,
|
||||
"note": "",
|
||||
"services": 70,
|
||||
"phonetic_name": "",
|
||||
"owner": 2,
|
||||
"security": 0,
|
||||
"attributes": [
|
||||
{
|
||||
"id": 1,
|
||||
"node_id": 4,
|
||||
"instance": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 2,
|
||||
"current_value": 0.0,
|
||||
"target_value": 0.0,
|
||||
"last_value": 1.0,
|
||||
"unit": "n/a",
|
||||
"step_value": 1.0,
|
||||
"editable": 1,
|
||||
"type": 337,
|
||||
"state": 1,
|
||||
"last_changed": 1678284911,
|
||||
"changed_by": 1,
|
||||
"changed_by_id": 0,
|
||||
"based_on": 1,
|
||||
"data": "",
|
||||
"name": "",
|
||||
"options": {
|
||||
"can_observe": [300],
|
||||
"observes": [72]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Test Cover",
|
||||
"name": "Shutter with position and slats",
|
||||
"profile": 2002,
|
||||
"image": "default",
|
||||
"favorite": 0,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Test Slats",
|
||||
"name": "Slats & Position",
|
||||
"profile": 2002,
|
||||
"image": "default",
|
||||
"favorite": 0,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Test Cover",
|
||||
"id": 2,
|
||||
"name": "No Position",
|
||||
"profile": 2002,
|
||||
"image": "default",
|
||||
"favorite": 0,
|
||||
@@ -20,7 +20,7 @@
|
||||
"attributes": [
|
||||
{
|
||||
"id": 1,
|
||||
"node_id": 3,
|
||||
"node_id": 2,
|
||||
"instance": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 4,
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"node_id": 3,
|
||||
"node_id": 2,
|
||||
"instance": 0,
|
||||
"minimum": 0,
|
||||
"maximum": 0,
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
# serializer version: 1
|
||||
# name: test_cover_snapshot[cover.no_position-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'cover',
|
||||
'entity_category': None,
|
||||
'entity_id': 'cover.no_position',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <CoverDeviceClass.SHUTTER: 'shutter'>,
|
||||
'original_icon': None,
|
||||
'original_name': None,
|
||||
'platform': 'homee',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 11>,
|
||||
'translation_key': None,
|
||||
'unique_id': '00055511EECC-2-1',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_cover_snapshot[cover.no_position-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'shutter',
|
||||
'friendly_name': 'No Position',
|
||||
'is_closed': True,
|
||||
'supported_features': <CoverEntityFeature: 11>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.no_position',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'closed',
|
||||
})
|
||||
# ---
|
||||
# name: test_cover_snapshot[cover.shutter_with_position_and_slats-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'cover',
|
||||
'entity_category': None,
|
||||
'entity_id': 'cover.shutter_with_position_and_slats',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <CoverDeviceClass.SHUTTER: 'shutter'>,
|
||||
'original_icon': None,
|
||||
'original_name': None,
|
||||
'platform': 'homee',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 143>,
|
||||
'translation_key': None,
|
||||
'unique_id': '00055511EECC-3-1',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_cover_snapshot[cover.shutter_with_position_and_slats-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'current_position': 100,
|
||||
'current_tilt_position': 100,
|
||||
'device_class': 'shutter',
|
||||
'friendly_name': 'Shutter with position and slats',
|
||||
'is_closed': False,
|
||||
'supported_features': <CoverEntityFeature: 143>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.shutter_with_position_and_slats',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'open',
|
||||
})
|
||||
# ---
|
||||
# name: test_cover_snapshot[cover.slats_position-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': list([
|
||||
None,
|
||||
]),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'cover',
|
||||
'entity_category': None,
|
||||
'entity_id': 'cover.slats_position',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'object_id_base': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <CoverDeviceClass.SHUTTER: 'shutter'>,
|
||||
'original_icon': None,
|
||||
'original_name': None,
|
||||
'platform': 'homee',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': <CoverEntityFeature: 176>,
|
||||
'translation_key': None,
|
||||
'unique_id': '00055511EECC-1-0',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_cover_snapshot[cover.slats_position-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'current_tilt_position': 65,
|
||||
'device_class': 'shutter',
|
||||
'friendly_name': 'Slats & Position',
|
||||
'is_closed': False,
|
||||
'supported_features': <CoverEntityFeature: 176>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'cover.slats_position',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'open',
|
||||
})
|
||||
# ---
|
||||
@@ -744,7 +744,7 @@
|
||||
'history': 1,
|
||||
'id': 3,
|
||||
'image': 'default',
|
||||
'name': 'Test Cover',
|
||||
'name': 'Shutter with position and slats',
|
||||
'note': 'TestCoverDevice',
|
||||
'order': 4,
|
||||
'owner': 2,
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
'manufacturer': None,
|
||||
'model': 'shutter_position_switch',
|
||||
'model_id': None,
|
||||
'name': 'Test Cover',
|
||||
'name': 'Shutter with position and slats',
|
||||
'name_by_user': None,
|
||||
'primary_config_entry': <ANY>,
|
||||
'serial_number': None,
|
||||
|
||||
@@ -4,6 +4,7 @@ from collections.abc import AsyncGenerator
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
from websockets import frames
|
||||
from websockets.exceptions import ConnectionClosed
|
||||
|
||||
@@ -33,11 +34,12 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import build_mock_node, setup_integration
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.common import MockConfigEntry, snapshot_platform
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@@ -61,19 +63,19 @@ async def test_open_close_stop_cover(
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover"},
|
||||
{ATTR_ENTITY_ID: "cover.shutter_with_position_and_slats"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover"},
|
||||
{ATTR_ENTITY_ID: "cover.shutter_with_position_and_slats"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_STOP_COVER,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover"},
|
||||
{ATTR_ENTITY_ID: "cover.shutter_with_position_and_slats"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -97,13 +99,13 @@ async def test_open_close_reverse_cover(
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover"},
|
||||
{ATTR_ENTITY_ID: "cover.shutter_with_position_and_slats"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover"},
|
||||
{ATTR_ENTITY_ID: "cover.shutter_with_position_and_slats"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -126,19 +128,19 @@ async def test_set_cover_position(
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover", ATTR_POSITION: 100},
|
||||
{ATTR_ENTITY_ID: "cover.shutter_with_position_and_slats", ATTR_POSITION: 100},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover", ATTR_POSITION: 0},
|
||||
{ATTR_ENTITY_ID: "cover.shutter_with_position_and_slats", ATTR_POSITION: 0},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_POSITION,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover", ATTR_POSITION: 50},
|
||||
{ATTR_ENTITY_ID: "cover.shutter_with_position_and_slats", ATTR_POSITION: 50},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -158,7 +160,7 @@ async def test_close_open_slats(
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
attributes = hass.states.get("cover.test_slats").attributes
|
||||
attributes = hass.states.get("cover.slats_position").attributes
|
||||
assert attributes.get("supported_features") == (
|
||||
CoverEntityFeature.OPEN_TILT
|
||||
| CoverEntityFeature.CLOSE_TILT
|
||||
@@ -168,13 +170,13 @@ async def test_close_open_slats(
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: "cover.test_slats"},
|
||||
{ATTR_ENTITY_ID: "cover.slats_position"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: "cover.test_slats"},
|
||||
{ATTR_ENTITY_ID: "cover.slats_position"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -194,7 +196,7 @@ async def test_close_open_reversed_slats(
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
attributes = hass.states.get("cover.test_slats").attributes
|
||||
attributes = hass.states.get("cover.slats_position").attributes
|
||||
assert attributes.get("supported_features") == (
|
||||
CoverEntityFeature.OPEN_TILT
|
||||
| CoverEntityFeature.CLOSE_TILT
|
||||
@@ -204,13 +206,13 @@ async def test_close_open_reversed_slats(
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_CLOSE_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: "cover.test_slats"},
|
||||
{ATTR_ENTITY_ID: "cover.slats_position"},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER_TILT,
|
||||
{ATTR_ENTITY_ID: "cover.test_slats"},
|
||||
{ATTR_ENTITY_ID: "cover.slats_position"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -233,19 +235,19 @@ async def test_set_slat_position(
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_TILT_POSITION,
|
||||
{ATTR_ENTITY_ID: "cover.test_slats", ATTR_TILT_POSITION: 100},
|
||||
{ATTR_ENTITY_ID: "cover.slats_position", ATTR_TILT_POSITION: 100},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_TILT_POSITION,
|
||||
{ATTR_ENTITY_ID: "cover.test_slats", ATTR_TILT_POSITION: 0},
|
||||
{ATTR_ENTITY_ID: "cover.slats_position", ATTR_TILT_POSITION: 0},
|
||||
blocking=True,
|
||||
)
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_SET_COVER_TILT_POSITION,
|
||||
{ATTR_ENTITY_ID: "cover.test_slats", ATTR_TILT_POSITION: 50},
|
||||
{ATTR_ENTITY_ID: "cover.slats_position", ATTR_TILT_POSITION: 50},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -269,9 +271,12 @@ async def test_cover_positions(
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert hass.states.get("cover.test_cover").state == CoverState.OPEN
|
||||
assert (
|
||||
hass.states.get("cover.shutter_with_position_and_slats").state
|
||||
== CoverState.OPEN
|
||||
)
|
||||
|
||||
attributes = hass.states.get("cover.test_cover").attributes
|
||||
attributes = hass.states.get("cover.shutter_with_position_and_slats").attributes
|
||||
assert attributes.get("supported_features") == (
|
||||
CoverEntityFeature.OPEN
|
||||
| CoverEntityFeature.CLOSE
|
||||
@@ -288,10 +293,13 @@ async def test_cover_positions(
|
||||
cover.add_on_changed_listener.call_args_list[0][0][0](cover)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
attributes = hass.states.get("cover.test_cover").attributes
|
||||
attributes = hass.states.get("cover.shutter_with_position_and_slats").attributes
|
||||
assert attributes.get("current_position") == 0
|
||||
assert attributes.get("current_tilt_position") == 0
|
||||
assert hass.states.get("cover.test_cover").state == CoverState.CLOSED
|
||||
assert (
|
||||
hass.states.get("cover.shutter_with_position_and_slats").state
|
||||
== CoverState.CLOSED
|
||||
)
|
||||
|
||||
cover.attributes[0].current_value = 3
|
||||
cover.attributes[1].current_value = 75
|
||||
@@ -299,8 +307,11 @@ async def test_cover_positions(
|
||||
cover.add_on_changed_listener.call_args_list[0][0][0](cover)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("cover.test_cover").state == CoverState.OPENING
|
||||
attributes = hass.states.get("cover.test_cover").attributes
|
||||
assert (
|
||||
hass.states.get("cover.shutter_with_position_and_slats").state
|
||||
== CoverState.OPENING
|
||||
)
|
||||
attributes = hass.states.get("cover.shutter_with_position_and_slats").attributes
|
||||
assert attributes.get("current_position") == 25
|
||||
assert attributes.get("current_tilt_position") == 25
|
||||
|
||||
@@ -310,8 +321,11 @@ async def test_cover_positions(
|
||||
cover.add_on_changed_listener.call_args_list[0][0][0](cover)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("cover.test_cover").state == CoverState.CLOSING
|
||||
attributes = hass.states.get("cover.test_cover").attributes
|
||||
assert (
|
||||
hass.states.get("cover.shutter_with_position_and_slats").state
|
||||
== CoverState.CLOSING
|
||||
)
|
||||
attributes = hass.states.get("cover.shutter_with_position_and_slats").attributes
|
||||
assert attributes.get("current_position") == 75
|
||||
assert attributes.get("current_tilt_position") == 74
|
||||
|
||||
@@ -331,17 +345,30 @@ async def test_reversed_cover(
|
||||
cover.add_on_changed_listener.call_args_list[0][0][0](cover)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
attributes = hass.states.get("cover.test_cover").attributes
|
||||
attributes = hass.states.get("cover.no_position").attributes
|
||||
assert attributes.get("supported_features") == (
|
||||
CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE | CoverEntityFeature.STOP
|
||||
)
|
||||
assert hass.states.get("cover.test_cover").state == CoverState.OPEN
|
||||
assert hass.states.get("cover.no_position").state == CoverState.OPEN
|
||||
|
||||
cover.attributes[0].current_value = 0
|
||||
cover.add_on_changed_listener.call_args_list[0][0][0](cover)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("cover.test_cover").state == CoverState.CLOSED
|
||||
assert hass.states.get("cover.no_position").state == CoverState.CLOSED
|
||||
|
||||
|
||||
async def test_invalid_cover(
|
||||
hass: HomeAssistant,
|
||||
mock_homee: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Test a cover that has no Attribute for is_closed state."""
|
||||
mock_homee.nodes = [build_mock_node("cover_invalid.json")]
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
assert "Cover Invalid Cover could not be added, " in caplog.text
|
||||
|
||||
|
||||
async def test_send_error(
|
||||
@@ -361,7 +388,7 @@ async def test_send_error(
|
||||
await hass.services.async_call(
|
||||
COVER_DOMAIN,
|
||||
SERVICE_OPEN_COVER,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover"},
|
||||
{ATTR_ENTITY_ID: "cover.no_position"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
@@ -379,19 +406,19 @@ async def test_node_entity_connection_listener(
|
||||
mock_homee.get_node_by_id.return_value = mock_homee.nodes[0]
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
states = hass.states.get("cover.test_cover")
|
||||
states = hass.states.get("cover.shutter_with_position_and_slats")
|
||||
assert states.state != STATE_UNAVAILABLE
|
||||
|
||||
await mock_homee.add_connection_listener.call_args_list[1][0][0](False)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
states = hass.states.get("cover.test_cover")
|
||||
states = hass.states.get("cover.shutter_with_position_and_slats")
|
||||
assert states.state == STATE_UNAVAILABLE
|
||||
|
||||
await mock_homee.add_connection_listener.call_args_list[1][0][0](True)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
states = hass.states.get("cover.test_cover")
|
||||
states = hass.states.get("cover.shutter_with_position_and_slats")
|
||||
assert states.state != STATE_UNAVAILABLE
|
||||
|
||||
|
||||
@@ -409,8 +436,28 @@ async def test_node_entity_update_action(
|
||||
await hass.services.async_call(
|
||||
HA_DOMAIN,
|
||||
SERVICE_UPDATE_ENTITY,
|
||||
{ATTR_ENTITY_ID: "cover.test_cover"},
|
||||
{ATTR_ENTITY_ID: "cover.shutter_with_position_and_slats"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_homee.update_node.assert_called_once_with(3)
|
||||
|
||||
|
||||
async def test_cover_snapshot(
|
||||
hass: HomeAssistant,
|
||||
mock_homee: MagicMock,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test snapshot of covers to assert cover_invalid is not created."""
|
||||
mock_homee.nodes = [
|
||||
build_mock_node("cover_with_slats_position.json"),
|
||||
build_mock_node("cover_without_position.json"),
|
||||
build_mock_node("cover_with_position_slats.json"),
|
||||
build_mock_node("cover_invalid.json"),
|
||||
]
|
||||
mock_homee.get_node_by_id = lambda node_id: mock_homee.nodes[node_id - 1]
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
@@ -107,7 +107,7 @@ async def test_software_version(
|
||||
mock_homee.nodes = [build_mock_node("cover_without_position.json")]
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, f"{HOMEE_ID}-3")})
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, f"{HOMEE_ID}-2")})
|
||||
assert device.sw_version == "1.45"
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ async def test_invalid_profile(
|
||||
mock_homee.nodes[0].profile = 77
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, f"{HOMEE_ID}-3")})
|
||||
device = device_registry.async_get_device(identifiers={(DOMAIN, f"{HOMEE_ID}-2")})
|
||||
assert device.model is None
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user