zwave refactor, don't use ozw values directly in properties. (#5961)

* First round of not using values directly

* Round two

* lint

* Round four

* Conflict

* Round five

* Update zwave.py

* round six

* Docstring

* flakywakie

* Fetch values in constructor

* Blank line removal

* Set attributes in callback

* Docstring

* Round seven

* Ughgit add homeassistant/components/lock/zwave.py!

* Sloppy code
This commit is contained in:
John Arild Berentsen 2017-02-18 08:56:05 +01:00 committed by Paulus Schoutsen
parent c1eed148cc
commit 799fbe42f8
8 changed files with 78 additions and 76 deletions

View File

@ -50,13 +50,18 @@ class ZWaveBinarySensor(BinarySensorDevice, zwave.ZWaveDeviceEntity):
def __init__(self, value, device_class): def __init__(self, value, device_class):
"""Initialize the sensor.""" """Initialize the sensor."""
self._sensor_type = device_class
zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN) zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN)
self._sensor_type = device_class
self._state = self._value.data
def update_properties(self):
"""Callback on data changes for node values."""
self._state = self._value.data
@property @property
def is_on(self): def is_on(self):
"""Return True if the binary sensor is on.""" """Return True if the binary sensor is on."""
return self._value.data return self._state
@property @property
def device_class(self): def device_class(self):
@ -80,26 +85,23 @@ class ZWaveTriggerSensor(ZWaveBinarySensor):
self.invalidate_after = dt_util.utcnow() + datetime.timedelta( self.invalidate_after = dt_util.utcnow() + datetime.timedelta(
seconds=self.re_arm_sec) seconds=self.re_arm_sec)
# If it's active make sure that we set the timeout tracker # If it's active make sure that we set the timeout tracker
if value.data: track_point_in_time(
track_point_in_time( self._hass, self.async_update_ha_state,
self._hass, self.async_update_ha_state, self.invalidate_after)
self.invalidate_after)
def value_changed(self, value): def update_properties(self):
"""Called when a value for this entity's node has changed.""" """Called when a value for this entity's node has changed."""
if self._value.value_id == value.value_id: self._state = self._value.data
self.schedule_update_ha_state() # only allow this value to be true for re_arm secs
if value.data: self.invalidate_after = dt_util.utcnow() + datetime.timedelta(
# only allow this value to be true for re_arm secs seconds=self.re_arm_sec)
self.invalidate_after = dt_util.utcnow() + datetime.timedelta( track_point_in_time(
seconds=self.re_arm_sec) self._hass, self.async_update_ha_state,
track_point_in_time( self.invalidate_after)
self._hass, self.async_update_ha_state,
self.invalidate_after)
@property @property
def is_on(self): def is_on(self):
"""Return True if movement has happened within the rearm time.""" """Return True if movement has happened within the rearm time."""
return self._value.data and \ return self._state and \
(self.invalidate_after is None or (self.invalidate_after is None or
self.invalidate_after > dt_util.utcnow()) self.invalidate_after > dt_util.utcnow())

View File

@ -68,7 +68,6 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
self._unit = temp_unit self._unit = temp_unit
_LOGGER.debug("temp_unit is %s", self._unit) _LOGGER.debug("temp_unit is %s", self._unit)
self._zxt_120 = None self._zxt_120 = None
self.update_properties()
# Make sure that we have values for the key before converting to int # Make sure that we have values for the key before converting to int
if (value.node.manufacturer_id.strip() and if (value.node.manufacturer_id.strip() and
value.node.product_id.strip()): value.node.product_id.strip()):
@ -79,6 +78,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice):
_LOGGER.debug("Remotec ZXT-120 Zwave Thermostat" _LOGGER.debug("Remotec ZXT-120 Zwave Thermostat"
" workaround") " workaround")
self._zxt_120 = 1 self._zxt_120 = 1
self.update_properties()
def update_properties(self): def update_properties(self):
"""Callback on data changes for node values.""" """Callback on data changes for node values."""

View File

@ -50,9 +50,11 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, CoverDevice):
self._open_id = None self._open_id = None
self._close_id = None self._close_id = None
self._current_position = None self._current_position = None
self._workaround = workaround.get_device_mapping(value) self._workaround = workaround.get_device_mapping(value)
if self._workaround: if self._workaround:
_LOGGER.debug("Using workaround %s", self._workaround) _LOGGER.debug("Using workaround %s", self._workaround)
self.update_properties()
def update_properties(self): def update_properties(self):
"""Callback on data changes for node values.""" """Callback on data changes for node values."""
@ -115,11 +117,16 @@ class ZwaveGarageDoor(zwave.ZWaveDeviceEntity, CoverDevice):
def __init__(self, value): def __init__(self, value):
"""Initialize the zwave garage door.""" """Initialize the zwave garage door."""
ZWaveDeviceEntity.__init__(self, value, DOMAIN) ZWaveDeviceEntity.__init__(self, value, DOMAIN)
self.update_properties()
def update_properties(self):
"""Callback on data changes for node values."""
self._state = self._value.data
@property @property
def is_closed(self): def is_closed(self):
"""Return the current position of Zwave garage door.""" """Return the current position of Zwave garage door."""
return not self._value.data return not self._state
def close_cover(self): def close_cover(self):
"""Close the garage door.""" """Close the garage door."""

View File

@ -107,13 +107,12 @@ class ZwaveDimmer(zwave.ZWaveDeviceEntity, Light):
_LOGGER.debug("AEOTEC ZW098 workaround enabled") _LOGGER.debug("AEOTEC ZW098 workaround enabled")
self._zw098 = 1 self._zw098 = 1
self.update_properties()
# Used for value change event handling # Used for value change event handling
self._refreshing = False self._refreshing = False
self._timer = None self._timer = None
_LOGGER.debug('self._refreshing=%s self.delay=%s', _LOGGER.debug('self._refreshing=%s self.delay=%s',
self._refresh_value, self._delay) self._refresh_value, self._delay)
self.update_properties()
def update_properties(self): def update_properties(self):
"""Update internal properties based on zwave values.""" """Update internal properties based on zwave values."""

View File

@ -234,11 +234,7 @@ class ZwaveLock(zwave.ZWaveDeviceEntity, LockDevice):
def update_properties(self): def update_properties(self):
"""Callback on data changes for node values.""" """Callback on data changes for node values."""
self._state = self.get_value(class_id=zwave self._state = self._value.data
.const.COMMAND_CLASS_DOOR_LOCK,
type=zwave.const.TYPE_BOOL,
genre=zwave.const.GENRE_USER,
member='data')
_LOGGER.debug('Lock state set from Bool value and' _LOGGER.debug('Lock state set from Bool value and'
' is %s', self._state) ' is %s', self._state)
notification_data = self.get_value(class_id=zwave.const notification_data = self.get_value(class_id=zwave.const

View File

@ -53,6 +53,12 @@ class ZWaveSensor(zwave.ZWaveDeviceEntity):
def __init__(self, value): def __init__(self, value):
"""Initialize the sensor.""" """Initialize the sensor."""
zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN) zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN)
self.update_properties()
def update_properties(self):
"""Callback on data changes for node values."""
self._state = self._value.data
self._units = self._value.units
@property @property
def force_update(self): def force_update(self):
@ -62,12 +68,12 @@ class ZWaveSensor(zwave.ZWaveDeviceEntity):
@property @property
def state(self): def state(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._value.data return self._state
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
"""Return the unit of measurement the value is expressed in.""" """Return the unit of measurement the value is expressed in."""
return self._value.units return self._units
class ZWaveMultilevelSensor(ZWaveSensor): class ZWaveMultilevelSensor(ZWaveSensor):
@ -76,26 +82,22 @@ class ZWaveMultilevelSensor(ZWaveSensor):
@property @property
def state(self): def state(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
value = self._value.data if self._units in ('C', 'F'):
return round(self._state, 1)
elif isinstance(self._state, float):
return round(self._state, 2)
if self._value.units in ('C', 'F'): return self._state
return round(value, 1)
elif isinstance(value, float):
return round(value, 2)
return value
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
"""Return the unit the value is expressed in.""" """Return the unit the value is expressed in."""
unit = self._value.units if self._units == 'C':
if unit == 'C':
return TEMP_CELSIUS return TEMP_CELSIUS
elif unit == 'F': elif self._units == 'F':
return TEMP_FAHRENHEIT return TEMP_FAHRENHEIT
else: else:
return unit return self._units
class ZWaveAlarmSensor(ZWaveSensor): class ZWaveAlarmSensor(ZWaveSensor):

View File

@ -38,11 +38,16 @@ class ZwaveSwitch(zwave.ZWaveDeviceEntity, SwitchDevice):
def __init__(self, value): def __init__(self, value):
"""Initialize the Z-Wave switch device.""" """Initialize the Z-Wave switch device."""
zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN) zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN)
self.update_properties()
def update_properties(self):
"""Callback on data changes for node values."""
self._state = self._value.data
@property @property
def is_on(self): def is_on(self):
"""Return true if device is on.""" """Return true if device is on."""
return self._value.data return self._state
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn the device on.""" """Turn the device on."""

View File

@ -262,22 +262,6 @@ def get_config_value(node, value_index, tries=5):
return None return None
def _get_wakeup(node, tries=5):
"""Return wakeup interval of the node or None if node is not wakable."""
try:
if node.can_wake_up():
for value_id in node.get_values(
class_id=const.COMMAND_CLASS_WAKE_UP):
return node.values[value_id].data
except RuntimeError:
# If we get an runtime error the dict has changed while
# we was looking for a value, just do it again
return None if tries <= 0 else _get_wakeup(
node, tries=tries - 1)
return None
# pylint: disable=R0914 # pylint: disable=R0914
def setup(hass, config): def setup(hass, config):
"""Setup Z-Wave. """Setup Z-Wave.
@ -692,6 +676,7 @@ class ZWaveDeviceEntity(Entity):
from pydispatch import dispatcher from pydispatch import dispatcher
self._value = value self._value = value
self.entity_id = "{}.{}".format(domain, self._object_id()) self.entity_id = "{}.{}".format(domain, self._object_id())
self._update_attributes()
dispatcher.connect( dispatcher.connect(
self.network_value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) self.network_value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED)
@ -705,12 +690,28 @@ class ZWaveDeviceEntity(Entity):
def value_changed(self, value): def value_changed(self, value):
"""Called when a value for this entity's node has changed.""" """Called when a value for this entity's node has changed."""
self._update_attributes()
self.update_properties() self.update_properties()
self.schedule_update_ha_state() self.schedule_update_ha_state()
def _update_attributes(self):
"""Update the node attributes. May only be used inside callback."""
self.node_id = self._value.node.node_id
self.location = self._value.node.location
self.battery_level = self._value.node.get_battery_level()
self.wakeup_interval = None
if self._value.node.can_wake_up():
self.wakeup_interval = self.get_value(
class_id=const.COMMAND_CLASS_WAKE_UP,
member='data')
def _value_handler(self, method=None, class_id=None, index=None, def _value_handler(self, method=None, class_id=None, index=None,
label=None, data=None, member=None, **kwargs): label=None, data=None, member=None, **kwargs):
"""Get the values for a given command_class with arguments.""" """Get the values for a given command_class with arguments.
May only be used inside callback.
"""
if class_id is not None: if class_id is not None:
kwargs[CLASS_ID] = class_id kwargs[CLASS_ID] = class_id
_LOGGER.debug('method=%s, class_id=%s, index=%s, label=%s, data=%s,' _LOGGER.debug('method=%s, class_id=%s, index=%s, label=%s, data=%s,'
@ -746,7 +747,7 @@ class ZWaveDeviceEntity(Entity):
return results return results
def get_value(self, **kwargs): def get_value(self, **kwargs):
"""Simplifyer to get values.""" """Simplifyer to get values. May only be used inside callback."""
return self._value_handler(method='get', **kwargs) return self._value_handler(method='get', **kwargs)
def set_value(self, **kwargs): def set_value(self, **kwargs):
@ -785,26 +786,16 @@ class ZWaveDeviceEntity(Entity):
def device_state_attributes(self): def device_state_attributes(self):
"""Return the device specific state attributes.""" """Return the device specific state attributes."""
attrs = { attrs = {
const.ATTR_NODE_ID: self._value.node.node_id, const.ATTR_NODE_ID: self.node_id,
} }
try: if self.battery_level is not None:
battery_level = self._value.node.get_battery_level() attrs[ATTR_BATTERY_LEVEL] = self.battery_level
except RuntimeError:
# If we get an runtime error the dict has changed while
# we was looking for a value, just do it again
battery_level = self._value.node.get_battery_level()
if battery_level is not None: if self.location:
attrs[ATTR_BATTERY_LEVEL] = battery_level attrs[ATTR_LOCATION] = self.location
location = self._value.node.location if self.wakeup_interval is not None:
attrs[ATTR_WAKEUP] = self.wakeup_interval
if location:
attrs[ATTR_LOCATION] = location
wakeup = _get_wakeup(self._value.node)
if wakeup:
attrs[ATTR_WAKEUP] = wakeup
return attrs return attrs