Handle missing value in all platforms of zwave_js (#46081)

This commit is contained in:
Marcel van der Veldt 2021-02-06 14:02:03 +01:00 committed by GitHub
parent fb68bf85ae
commit 242ff045b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 14 deletions

View file

@ -207,6 +207,9 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity):
if self._current_mode is None: if self._current_mode is None:
# Thermostat(valve) with no support for setting a mode is considered heating-only # Thermostat(valve) with no support for setting a mode is considered heating-only
return HVAC_MODE_HEAT return HVAC_MODE_HEAT
if self._current_mode.value is None:
# guard missing value
return HVAC_MODE_HEAT
return ZW_HVAC_MODE_MAP.get(int(self._current_mode.value), HVAC_MODE_HEAT_COOL) return ZW_HVAC_MODE_MAP.get(int(self._current_mode.value), HVAC_MODE_HEAT_COOL)
@property @property
@ -219,6 +222,9 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity):
"""Return the current running hvac operation if supported.""" """Return the current running hvac operation if supported."""
if not self._operating_state: if not self._operating_state:
return None return None
if self._operating_state.value is None:
# guard missing value
return None
return HVAC_CURRENT_MAP.get(int(self._operating_state.value)) return HVAC_CURRENT_MAP.get(int(self._operating_state.value))
@property @property
@ -234,12 +240,18 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity):
@property @property
def target_temperature(self) -> Optional[float]: def target_temperature(self) -> Optional[float]:
"""Return the temperature we try to reach.""" """Return the temperature we try to reach."""
if self._current_mode and self._current_mode.value is None:
# guard missing value
return None
temp = self._setpoint_value(self._current_mode_setpoint_enums[0]) temp = self._setpoint_value(self._current_mode_setpoint_enums[0])
return temp.value if temp else None return temp.value if temp else None
@property @property
def target_temperature_high(self) -> Optional[float]: def target_temperature_high(self) -> Optional[float]:
"""Return the highbound target temperature we try to reach.""" """Return the highbound target temperature we try to reach."""
if self._current_mode and self._current_mode.value is None:
# guard missing value
return None
temp = self._setpoint_value(self._current_mode_setpoint_enums[1]) temp = self._setpoint_value(self._current_mode_setpoint_enums[1])
return temp.value if temp else None return temp.value if temp else None
@ -251,6 +263,9 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity):
@property @property
def preset_mode(self) -> Optional[str]: def preset_mode(self) -> Optional[str]:
"""Return the current preset mode, e.g., home, away, temp.""" """Return the current preset mode, e.g., home, away, temp."""
if self._current_mode and self._current_mode.value is None:
# guard missing value
return None
if self._current_mode and int(self._current_mode.value) not in THERMOSTAT_MODES: if self._current_mode and int(self._current_mode.value) not in THERMOSTAT_MODES:
return_val: str = self._current_mode.metadata.states.get( return_val: str = self._current_mode.metadata.states.get(
self._current_mode.value self._current_mode.value

View file

@ -1,6 +1,6 @@
"""Support for Z-Wave cover devices.""" """Support for Z-Wave cover devices."""
import logging import logging
from typing import Any, Callable, List from typing import Any, Callable, List, Optional
from zwave_js_server.client import Client as ZwaveClient from zwave_js_server.client import Client as ZwaveClient
@ -59,13 +59,19 @@ class ZWaveCover(ZWaveBaseEntity, CoverEntity):
"""Representation of a Z-Wave Cover device.""" """Representation of a Z-Wave Cover device."""
@property @property
def is_closed(self) -> bool: def is_closed(self) -> Optional[bool]:
"""Return true if cover is closed.""" """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 == 0)
@property @property
def current_cover_position(self) -> int: def current_cover_position(self) -> Optional[int]:
"""Return the current position of cover where 0 means closed and 100 is fully open.""" """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((self.info.primary_value.value / 99) * 100) return round((self.info.primary_value.value / 99) * 100)
async def async_set_cover_position(self, **kwargs: Any) -> None: async def async_set_cover_position(self, **kwargs: Any) -> None:

View file

@ -102,13 +102,7 @@ class ZWaveBaseEntity(Entity):
@property @property
def available(self) -> bool: def available(self) -> bool:
"""Return entity availability.""" """Return entity availability."""
return ( return self.client.connected and bool(self.info.node.ready)
self.client.connected
and bool(self.info.node.ready)
# a None value indicates something wrong with the device,
# or the value is simply not yet there (it will arrive later).
and self.info.primary_value.value is not None
)
@callback @callback
def _value_changed(self, event_data: dict) -> None: def _value_changed(self, event_data: dict) -> None:

View file

@ -84,13 +84,19 @@ class ZwaveFan(ZWaveBaseEntity, FanEntity):
await self.info.node.async_set_value(target_value, 0) await self.info.node.async_set_value(target_value, 0)
@property @property
def is_on(self) -> bool: def is_on(self) -> Optional[bool]: # type: ignore
"""Return true if device is on (speed above 0).""" """Return true if device is on (speed above 0)."""
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 > 0)
@property @property
def percentage(self) -> int: def percentage(self) -> Optional[int]:
"""Return the current speed percentage.""" """Return the current speed percentage."""
if self.info.primary_value.value is None:
# guard missing value
return None
return ranged_value_to_percentage(SPEED_RANGE, self.info.primary_value.value) return ranged_value_to_percentage(SPEED_RANGE, self.info.primary_value.value)
@property @property

View file

@ -90,6 +90,9 @@ class ZWaveLock(ZWaveBaseEntity, LockEntity):
@property @property
def is_locked(self) -> Optional[bool]: def is_locked(self) -> Optional[bool]:
"""Return true if the lock is locked.""" """Return true if the lock is locked."""
if self.info.primary_value.value is None:
# guard missing value
return None
return int( return int(
LOCK_CMD_CLASS_TO_LOCKED_STATE_MAP[ LOCK_CMD_CLASS_TO_LOCKED_STATE_MAP[
CommandClass(self.info.primary_value.command_class) CommandClass(self.info.primary_value.command_class)

View file

@ -1,7 +1,7 @@
"""Representation of Z-Wave switches.""" """Representation of Z-Wave switches."""
import logging import logging
from typing import Any, Callable, List from typing import Any, Callable, List, Optional
from zwave_js_server.client import Client as ZwaveClient from zwave_js_server.client import Client as ZwaveClient
@ -44,8 +44,11 @@ class ZWaveSwitch(ZWaveBaseEntity, SwitchEntity):
"""Representation of a Z-Wave switch.""" """Representation of a Z-Wave switch."""
@property @property
def is_on(self) -> bool: def is_on(self) -> Optional[bool]: # type: ignore
"""Return a boolean for the state of the switch.""" """Return a boolean for the state of the switch."""
if self.info.primary_value.value is None:
# guard missing value
return None
return bool(self.info.primary_value.value) return bool(self.info.primary_value.value)
async def async_turn_on(self, **kwargs: Any) -> None: async def async_turn_on(self, **kwargs: Any) -> None: