Fix SmartThings Cover Set Position (for window shades) (#96612)
* Update smartthings dependencies * Update cover to support window_shade_level
This commit is contained in:
parent
1ace9ab82e
commit
4ae69787a2
5 changed files with 62 additions and 13 deletions
|
@ -62,7 +62,11 @@ def get_capabilities(capabilities: Sequence[str]) -> Sequence[str] | None:
|
||||||
# Must have one of the min_required
|
# Must have one of the min_required
|
||||||
if any(capability in capabilities for capability in min_required):
|
if any(capability in capabilities for capability in min_required):
|
||||||
# Return all capabilities supported/consumed
|
# Return all capabilities supported/consumed
|
||||||
return min_required + [Capability.battery, Capability.switch_level]
|
return min_required + [
|
||||||
|
Capability.battery,
|
||||||
|
Capability.switch_level,
|
||||||
|
Capability.window_shade_level,
|
||||||
|
]
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -74,12 +78,16 @@ class SmartThingsCover(SmartThingsEntity, CoverEntity):
|
||||||
"""Initialize the cover class."""
|
"""Initialize the cover class."""
|
||||||
super().__init__(device)
|
super().__init__(device)
|
||||||
self._device_class = None
|
self._device_class = None
|
||||||
|
self._current_cover_position = None
|
||||||
self._state = None
|
self._state = None
|
||||||
self._state_attrs = None
|
self._state_attrs = None
|
||||||
self._attr_supported_features = (
|
self._attr_supported_features = (
|
||||||
CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
|
CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
|
||||||
)
|
)
|
||||||
if Capability.switch_level in device.capabilities:
|
if (
|
||||||
|
Capability.switch_level in device.capabilities
|
||||||
|
or Capability.window_shade_level in device.capabilities
|
||||||
|
):
|
||||||
self._attr_supported_features |= CoverEntityFeature.SET_POSITION
|
self._attr_supported_features |= CoverEntityFeature.SET_POSITION
|
||||||
|
|
||||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
|
@ -103,7 +111,12 @@ class SmartThingsCover(SmartThingsEntity, CoverEntity):
|
||||||
if not self.supported_features & CoverEntityFeature.SET_POSITION:
|
if not self.supported_features & CoverEntityFeature.SET_POSITION:
|
||||||
return
|
return
|
||||||
# Do not set_status=True as device will report progress.
|
# Do not set_status=True as device will report progress.
|
||||||
await self._device.set_level(kwargs[ATTR_POSITION], 0)
|
if Capability.window_shade_level in self._device.capabilities:
|
||||||
|
await self._device.set_window_shade_level(
|
||||||
|
kwargs[ATTR_POSITION], set_status=False
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await self._device.set_level(kwargs[ATTR_POSITION], set_status=False)
|
||||||
|
|
||||||
async def async_update(self) -> None:
|
async def async_update(self) -> None:
|
||||||
"""Update the attrs of the cover."""
|
"""Update the attrs of the cover."""
|
||||||
|
@ -117,6 +130,11 @@ class SmartThingsCover(SmartThingsEntity, CoverEntity):
|
||||||
self._device_class = CoverDeviceClass.GARAGE
|
self._device_class = CoverDeviceClass.GARAGE
|
||||||
self._state = VALUE_TO_STATE.get(self._device.status.door)
|
self._state = VALUE_TO_STATE.get(self._device.status.door)
|
||||||
|
|
||||||
|
if Capability.window_shade_level in self._device.capabilities:
|
||||||
|
self._current_cover_position = self._device.status.shade_level
|
||||||
|
elif Capability.switch_level in self._device.capabilities:
|
||||||
|
self._current_cover_position = self._device.status.level
|
||||||
|
|
||||||
self._state_attrs = {}
|
self._state_attrs = {}
|
||||||
battery = self._device.status.attributes[Attribute.battery].value
|
battery = self._device.status.attributes[Attribute.battery].value
|
||||||
if battery is not None:
|
if battery is not None:
|
||||||
|
@ -142,9 +160,7 @@ class SmartThingsCover(SmartThingsEntity, CoverEntity):
|
||||||
@property
|
@property
|
||||||
def current_cover_position(self) -> int | None:
|
def current_cover_position(self) -> int | None:
|
||||||
"""Return current position of cover."""
|
"""Return current position of cover."""
|
||||||
if not self.supported_features & CoverEntityFeature.SET_POSITION:
|
return self._current_cover_position
|
||||||
return None
|
|
||||||
return self._device.status.level
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_class(self) -> CoverDeviceClass | None:
|
def device_class(self) -> CoverDeviceClass | None:
|
||||||
|
|
|
@ -30,5 +30,5 @@
|
||||||
"documentation": "https://www.home-assistant.io/integrations/smartthings",
|
"documentation": "https://www.home-assistant.io/integrations/smartthings",
|
||||||
"iot_class": "cloud_push",
|
"iot_class": "cloud_push",
|
||||||
"loggers": ["httpsig", "pysmartapp", "pysmartthings"],
|
"loggers": ["httpsig", "pysmartapp", "pysmartthings"],
|
||||||
"requirements": ["pysmartapp==0.3.3", "pysmartthings==0.7.6"]
|
"requirements": ["pysmartapp==0.3.5", "pysmartthings==0.7.8"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -2006,10 +2006,10 @@ pysma==0.7.3
|
||||||
pysmappee==0.2.29
|
pysmappee==0.2.29
|
||||||
|
|
||||||
# homeassistant.components.smartthings
|
# homeassistant.components.smartthings
|
||||||
pysmartapp==0.3.3
|
pysmartapp==0.3.5
|
||||||
|
|
||||||
# homeassistant.components.smartthings
|
# homeassistant.components.smartthings
|
||||||
pysmartthings==0.7.6
|
pysmartthings==0.7.8
|
||||||
|
|
||||||
# homeassistant.components.edl21
|
# homeassistant.components.edl21
|
||||||
pysml==0.0.12
|
pysml==0.0.12
|
||||||
|
|
|
@ -1492,10 +1492,10 @@ pysma==0.7.3
|
||||||
pysmappee==0.2.29
|
pysmappee==0.2.29
|
||||||
|
|
||||||
# homeassistant.components.smartthings
|
# homeassistant.components.smartthings
|
||||||
pysmartapp==0.3.3
|
pysmartapp==0.3.5
|
||||||
|
|
||||||
# homeassistant.components.smartthings
|
# homeassistant.components.smartthings
|
||||||
pysmartthings==0.7.6
|
pysmartthings==0.7.8
|
||||||
|
|
||||||
# homeassistant.components.edl21
|
# homeassistant.components.edl21
|
||||||
pysml==0.0.12
|
pysml==0.0.12
|
||||||
|
|
|
@ -113,8 +113,10 @@ async def test_close(hass: HomeAssistant, device_factory) -> None:
|
||||||
assert state.state == STATE_CLOSING
|
assert state.state == STATE_CLOSING
|
||||||
|
|
||||||
|
|
||||||
async def test_set_cover_position(hass: HomeAssistant, device_factory) -> None:
|
async def test_set_cover_position_switch_level(
|
||||||
"""Test the cover sets to the specific position."""
|
hass: HomeAssistant, device_factory
|
||||||
|
) -> None:
|
||||||
|
"""Test the cover sets to the specific position for legacy devices that use Capability.switch_level."""
|
||||||
# Arrange
|
# Arrange
|
||||||
device = device_factory(
|
device = device_factory(
|
||||||
"Shade",
|
"Shade",
|
||||||
|
@ -140,6 +142,37 @@ async def test_set_cover_position(hass: HomeAssistant, device_factory) -> None:
|
||||||
assert device._api.post_device_command.call_count == 1 # type: ignore
|
assert device._api.post_device_command.call_count == 1 # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
async def test_set_cover_position(hass: HomeAssistant, device_factory) -> None:
|
||||||
|
"""Test the cover sets to the specific position."""
|
||||||
|
# Arrange
|
||||||
|
device = device_factory(
|
||||||
|
"Shade",
|
||||||
|
[Capability.window_shade, Capability.battery, Capability.window_shade_level],
|
||||||
|
{
|
||||||
|
Attribute.window_shade: "opening",
|
||||||
|
Attribute.battery: 95,
|
||||||
|
Attribute.shade_level: 10,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await setup_platform(hass, COVER_DOMAIN, devices=[device])
|
||||||
|
# Act
|
||||||
|
await hass.services.async_call(
|
||||||
|
COVER_DOMAIN,
|
||||||
|
SERVICE_SET_COVER_POSITION,
|
||||||
|
{ATTR_POSITION: 50, "entity_id": "all"},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("cover.shade")
|
||||||
|
# Result of call does not update state
|
||||||
|
assert state.state == STATE_OPENING
|
||||||
|
assert state.attributes[ATTR_BATTERY_LEVEL] == 95
|
||||||
|
assert state.attributes[ATTR_CURRENT_POSITION] == 10
|
||||||
|
# Ensure API called
|
||||||
|
|
||||||
|
assert device._api.post_device_command.call_count == 1 # type: ignore
|
||||||
|
|
||||||
|
|
||||||
async def test_set_cover_position_unsupported(
|
async def test_set_cover_position_unsupported(
|
||||||
hass: HomeAssistant, device_factory
|
hass: HomeAssistant, device_factory
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue