Fix Matter cover deviceclass and inverted position (#92063)

This commit is contained in:
Marcel van der Veldt 2023-04-26 21:21:31 +02:00 committed by GitHub
parent e7e50243d1
commit 3c44c7416f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 23 deletions

View File

@ -8,6 +8,7 @@ from chip.clusters import Objects as clusters
from homeassistant.components.cover import ( from homeassistant.components.cover import (
ATTR_POSITION, ATTR_POSITION,
CoverDeviceClass,
CoverEntity, CoverEntity,
CoverEntityDescription, CoverEntityDescription,
CoverEntityFeature, CoverEntityFeature,
@ -25,6 +26,12 @@ from .models import MatterDiscoverySchema
# The MASK used for extracting bits 0 to 1 of the byte. # The MASK used for extracting bits 0 to 1 of the byte.
OPERATIONAL_STATUS_MASK = 0b11 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): class OperationalStatus(IntEnum):
"""Currently ongoing operations enumeration for coverings, as defined in the Matter spec.""" """Currently ongoing operations enumeration for coverings, as defined in the Matter spec."""
@ -56,20 +63,6 @@ class MatterCover(MatterEntity, CoverEntity):
| CoverEntityFeature.SET_POSITION | 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 @property
def is_closed(self) -> bool: def is_closed(self) -> bool:
"""Return true if cover is closed, else False.""" """Return true if cover is closed, else False."""
@ -91,7 +84,8 @@ class MatterCover(MatterEntity, CoverEntity):
"""Set the cover to a specific position.""" """Set the cover to a specific position."""
position = kwargs[ATTR_POSITION] position = kwargs[ATTR_POSITION]
await self.send_device_command( 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: 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_opening = False
self._attr_is_closing = 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 clusters.WindowCovering.Attributes.CurrentPositionLiftPercentage
) )
self._attr_current_cover_position = 100 - current_cover_position
LOGGER.debug( LOGGER.debug(
"Current position: %s for %s", "Current position for %s - raw: %s - corrected: %s",
self._attr_current_cover_position,
self.entity_id, 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 schema(s) to map Matter Attributes to HA entities
DISCOVERY_SCHEMAS = [ DISCOVERY_SCHEMAS = [
@ -149,5 +153,5 @@ DISCOVERY_SCHEMAS = [
clusters.WindowCovering.Attributes.CurrentPositionLiftPercentage, clusters.WindowCovering.Attributes.CurrentPositionLiftPercentage,
clusters.WindowCovering.Attributes.OperationalStatus, clusters.WindowCovering.Attributes.OperationalStatus,
), ),
), )
] ]

View File

@ -103,7 +103,7 @@ async def test_cover(
assert matter_client.send_device_command.call_args == call( assert matter_client.send_device_command.call_args == call(
node_id=window_covering.node_id, node_id=window_covering.node_id,
endpoint_id=1, endpoint_id=1,
command=clusters.WindowCovering.Commands.GoToLiftValue(50), command=clusters.WindowCovering.Commands.GoToLiftPercentage(5000),
) )
matter_client.send_device_command.reset_mock() matter_client.send_device_command.reset_mock()
@ -121,7 +121,7 @@ async def test_cover(
state = hass.states.get("cover.longan_link_wncv_da01") state = hass.states.get("cover.longan_link_wncv_da01")
assert state 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, 8, 50)
set_node_attribute(window_covering, 1, 258, 10, 1) 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") state = hass.states.get("cover.longan_link_wncv_da01")
assert state assert state
assert state.attributes["current_position"] == 100 assert state.attributes["current_position"] == 0
assert state.state == STATE_OPEN assert state.state == STATE_CLOSED