diff --git a/homeassistant/components/matter/cover.py b/homeassistant/components/matter/cover.py index 487594561d8..4e227d83b44 100644 --- a/homeassistant/components/matter/cover.py +++ b/homeassistant/components/matter/cover.py @@ -8,6 +8,7 @@ from chip.clusters import Objects as clusters from homeassistant.components.cover import ( ATTR_POSITION, + CoverDeviceClass, CoverEntity, CoverEntityDescription, CoverEntityFeature, @@ -25,6 +26,12 @@ from .models import MatterDiscoverySchema # The MASK used for extracting bits 0 to 1 of the byte. OPERATIONAL_STATUS_MASK = 0b11 +# map Matter window cover types to HA device class +TYPE_MAP = { + clusters.WindowCovering.Enums.Type.kAwning: CoverDeviceClass.AWNING, + clusters.WindowCovering.Enums.Type.kDrapery: CoverDeviceClass.CURTAIN, +} + class OperationalStatus(IntEnum): """Currently ongoing operations enumeration for coverings, as defined in the Matter spec.""" @@ -56,20 +63,6 @@ class MatterCover(MatterEntity, CoverEntity): | CoverEntityFeature.SET_POSITION ) - @property - def current_cover_position(self) -> int: - """Return the current position of cover.""" - if self._attr_current_cover_position: - current_position = self._attr_current_cover_position - else: - current_position = self.get_matter_attribute_value( - clusters.WindowCovering.Attributes.CurrentPositionLiftPercentage - ) - - assert current_position is not None - - return current_position - @property def is_closed(self) -> bool: """Return true if cover is closed, else False.""" @@ -91,7 +84,8 @@ class MatterCover(MatterEntity, CoverEntity): """Set the cover to a specific position.""" position = kwargs[ATTR_POSITION] await self.send_device_command( - clusters.WindowCovering.Commands.GoToLiftValue(position) + # value needs to be inverted and is sent in 100ths + clusters.WindowCovering.Commands.GoToLiftPercentage((100 - position) * 100) ) async def send_device_command(self, command: Any) -> None: @@ -129,15 +123,25 @@ class MatterCover(MatterEntity, CoverEntity): self._attr_is_opening = False self._attr_is_closing = False - self._attr_current_cover_position = self.get_matter_attribute_value( + # current position is inverted in matter (100 is closed, 0 is open) + current_cover_position = self.get_matter_attribute_value( clusters.WindowCovering.Attributes.CurrentPositionLiftPercentage ) + self._attr_current_cover_position = 100 - current_cover_position + LOGGER.debug( - "Current position: %s for %s", - self._attr_current_cover_position, + "Current position for %s - raw: %s - corrected: %s", self.entity_id, + current_cover_position, + self.current_cover_position, ) + # map matter type to HA deviceclass + device_type: clusters.WindowCovering.Enums.Type = ( + self.get_matter_attribute_value(clusters.WindowCovering.Attributes.Type) + ) + self._attr_device_class = TYPE_MAP.get(device_type, CoverDeviceClass.AWNING) + # Discovery schema(s) to map Matter Attributes to HA entities DISCOVERY_SCHEMAS = [ @@ -149,5 +153,5 @@ DISCOVERY_SCHEMAS = [ clusters.WindowCovering.Attributes.CurrentPositionLiftPercentage, clusters.WindowCovering.Attributes.OperationalStatus, ), - ), + ) ] diff --git a/tests/components/matter/test_cover.py b/tests/components/matter/test_cover.py index b967436f093..15ce8ceea8b 100644 --- a/tests/components/matter/test_cover.py +++ b/tests/components/matter/test_cover.py @@ -103,7 +103,7 @@ async def test_cover( assert matter_client.send_device_command.call_args == call( node_id=window_covering.node_id, endpoint_id=1, - command=clusters.WindowCovering.Commands.GoToLiftValue(50), + command=clusters.WindowCovering.Commands.GoToLiftPercentage(5000), ) matter_client.send_device_command.reset_mock() @@ -121,7 +121,7 @@ async def test_cover( state = hass.states.get("cover.longan_link_wncv_da01") assert state - assert state.state == STATE_CLOSED + assert state.state == STATE_OPEN set_node_attribute(window_covering, 1, 258, 8, 50) set_node_attribute(window_covering, 1, 258, 10, 1) @@ -137,5 +137,5 @@ async def test_cover( state = hass.states.get("cover.longan_link_wncv_da01") assert state - assert state.attributes["current_position"] == 100 - assert state.state == STATE_OPEN + assert state.attributes["current_position"] == 0 + assert state.state == STATE_CLOSED