Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code quality improvements to zwave covers and sensors #90492

Closed
wants to merge 15 commits into from
96 changes: 59 additions & 37 deletions homeassistant/components/zwave_js/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,36 +66,6 @@ def async_add_cover(info: ZwaveDiscoveryInfo) -> None:
)


def percent_to_zwave_position(value: int) -> int:
"""Convert position in 0-100 scale to 0-99 scale.

`value` -- (int) Position byte value from 0-100.
"""
if value > 0:
return max(1, round((value / 100) * 99))
return 0


def percent_to_zwave_tilt(value: int) -> int:
"""Convert position in 0-100 scale to 0-99 scale.

`value` -- (int) Position byte value from 0-100.
"""
if value > 0:
return round((value / 100) * 99)
return 0


def zwave_tilt_to_percent(value: int) -> int:
"""Convert 0-99 scale to position in 0-100 scale.

`value` -- (int) Position byte value from 0-99.
"""
if value > 0:
return round((value / 99) * 100)
return 0


class ZWaveCover(ZWaveBaseEntity, CoverEntity):
"""Representation of a Z-Wave Cover device."""

Expand Down Expand Up @@ -130,41 +100,75 @@ def __init__(
if self.info.platform_hint and self.info.platform_hint.startswith("blind"):
self._attr_device_class = CoverDeviceClass.BLIND

def percent_to_zwave_position(self, value: int) -> int:
"""Convert position in 0-100 scale to closed_value-open_value scale.

`value` -- (int) Position byte value from 0-100.
"""
if value > self._fully_closed_value:
return max(
1, round((value / 100) * self._cover_range) + self._fully_closed_value
)
return self._fully_closed_value

@property
def _fully_open_value(self) -> int:
"""Return value that represents fully opened."""
max_ = self.info.primary_value.metadata.max
return 99 if max_ is None else max_

@property
def _fully_closed_value(self) -> int:
"""Return value that represents fully closed."""
min_ = self.info.primary_value.metadata.min
return 0 if min_ is None else min_

@property
def _cover_range(self) -> int:
"""Return range between fully opened and fully closed."""
return self._fully_open_value - self._fully_closed_value

@property
def is_closed(self) -> bool | None:
"""Return true if cover is closed."""
if self.info.primary_value.value is None:
# guard missing value
return None
return bool(self.info.primary_value.value == 0)
return bool(self.info.primary_value.value == self._fully_closed_value)

@property
def current_cover_position(self) -> int | None:
"""Return the current position of cover where 0 means closed and 100 is fully open."""
if self.info.primary_value.value is None:
# guard missing value
return None
return round((cast(int, self.info.primary_value.value) / 99) * 100)
return round(
(
(cast(int, self.info.primary_value.value) - self._fully_closed_value)
/ self._cover_range
)
* 100
)

async def async_set_cover_position(self, **kwargs: Any) -> None:
"""Move the cover to a specific position."""
target_value = self.get_zwave_value(TARGET_VALUE_PROPERTY)
assert target_value is not None
await self.info.node.async_set_value(
target_value, percent_to_zwave_position(kwargs[ATTR_POSITION])
target_value, self.percent_to_zwave_position(kwargs[ATTR_POSITION])
)

async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the cover."""
target_value = self.get_zwave_value(TARGET_VALUE_PROPERTY)
assert target_value is not None
await self.info.node.async_set_value(target_value, 99)
await self.info.node.async_set_value(target_value, self._fully_open_value)

async def async_close_cover(self, **kwargs: Any) -> None:
"""Close cover."""
target_value = self.get_zwave_value(TARGET_VALUE_PROPERTY)
assert target_value is not None
await self.info.node.async_set_value(target_value, 0)
await self.info.node.async_set_value(target_value, self._fully_closed_value)

async def async_stop_cover(self, **kwargs: Any) -> None:
"""Stop cover."""
Expand Down Expand Up @@ -195,6 +199,24 @@ def __init__(
| CoverEntityFeature.SET_TILT_POSITION
)

def percent_to_zwave_tilt(self, value: int) -> int:
"""Convert position in 0-100 scale to closed_value-open_value scale.

`value` -- (int) Position byte value from 0-100.
"""
if value > self._fully_closed_value:
return round((value / 100) * self._cover_range) + self._fully_closed_value
return self._fully_closed_value

def zwave_tilt_to_percent(self, value: int) -> int:
"""Convert closed_value-open_value scale to position in 0-100 scale.

`value` -- (int) Position byte value from closed_value-open_value.
"""
if value > self._fully_closed_value:
return round(((value - self._fully_closed_value) / self._cover_range) * 100)
return self._fully_closed_value

@property
def current_cover_tilt_position(self) -> int | None:
"""Return current position of cover tilt.
Expand All @@ -204,14 +226,14 @@ def current_cover_tilt_position(self) -> int | None:
value = self._current_tilt_value
if value is None or value.value is None:
return None
return zwave_tilt_to_percent(int(value.value))
return self.zwave_tilt_to_percent(int(value.value))

async def async_set_cover_tilt_position(self, **kwargs: Any) -> None:
"""Move the cover tilt to a specific position."""
assert self._current_tilt_value
await self.info.node.async_set_value(
self._current_tilt_value,
percent_to_zwave_tilt(kwargs[ATTR_TILT_POSITION]),
self.percent_to_zwave_tilt(kwargs[ATTR_TILT_POSITION]),
)

async def async_open_cover_tilt(self, **kwargs: Any) -> None:
Expand Down
Loading