diff --git a/homeassistant/components/binary_sensor/zwave.py b/homeassistant/components/binary_sensor/zwave.py index f9bd417768b..3a8144d9188 100644 --- a/homeassistant/components/binary_sensor/zwave.py +++ b/homeassistant/components/binary_sensor/zwave.py @@ -50,13 +50,18 @@ class ZWaveBinarySensor(BinarySensorDevice, zwave.ZWaveDeviceEntity): def __init__(self, value, device_class): """Initialize the sensor.""" - self._sensor_type = device_class 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 def is_on(self): """Return True if the binary sensor is on.""" - return self._value.data + return self._state @property def device_class(self): @@ -80,26 +85,23 @@ class ZWaveTriggerSensor(ZWaveBinarySensor): self.invalidate_after = dt_util.utcnow() + datetime.timedelta( seconds=self.re_arm_sec) # If it's active make sure that we set the timeout tracker - if value.data: - track_point_in_time( - self._hass, self.async_update_ha_state, - self.invalidate_after) + track_point_in_time( + self._hass, self.async_update_ha_state, + self.invalidate_after) - def value_changed(self, value): + def update_properties(self): """Called when a value for this entity's node has changed.""" - if self._value.value_id == value.value_id: - self.schedule_update_ha_state() - if value.data: - # only allow this value to be true for re_arm secs - self.invalidate_after = dt_util.utcnow() + datetime.timedelta( - seconds=self.re_arm_sec) - track_point_in_time( - self._hass, self.async_update_ha_state, - self.invalidate_after) + self._state = self._value.data + # only allow this value to be true for re_arm secs + self.invalidate_after = dt_util.utcnow() + datetime.timedelta( + seconds=self.re_arm_sec) + track_point_in_time( + self._hass, self.async_update_ha_state, + self.invalidate_after) @property def is_on(self): """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 > dt_util.utcnow()) diff --git a/homeassistant/components/climate/zwave.py b/homeassistant/components/climate/zwave.py index e74d5d575a3..e069c5a1e17 100755 --- a/homeassistant/components/climate/zwave.py +++ b/homeassistant/components/climate/zwave.py @@ -68,7 +68,6 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): self._unit = temp_unit _LOGGER.debug("temp_unit is %s", self._unit) self._zxt_120 = None - self.update_properties() # Make sure that we have values for the key before converting to int if (value.node.manufacturer_id.strip() and value.node.product_id.strip()): @@ -79,6 +78,7 @@ class ZWaveClimate(ZWaveDeviceEntity, ClimateDevice): _LOGGER.debug("Remotec ZXT-120 Zwave Thermostat" " workaround") self._zxt_120 = 1 + self.update_properties() def update_properties(self): """Callback on data changes for node values.""" diff --git a/homeassistant/components/cover/zwave.py b/homeassistant/components/cover/zwave.py index 6278f3636b3..c1e3580370d 100644 --- a/homeassistant/components/cover/zwave.py +++ b/homeassistant/components/cover/zwave.py @@ -50,9 +50,11 @@ class ZwaveRollershutter(zwave.ZWaveDeviceEntity, CoverDevice): self._open_id = None self._close_id = None self._current_position = None + self._workaround = workaround.get_device_mapping(value) if self._workaround: _LOGGER.debug("Using workaround %s", self._workaround) + self.update_properties() def update_properties(self): """Callback on data changes for node values.""" @@ -115,11 +117,16 @@ class ZwaveGarageDoor(zwave.ZWaveDeviceEntity, CoverDevice): def __init__(self, value): """Initialize the zwave garage door.""" 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 def is_closed(self): """Return the current position of Zwave garage door.""" - return not self._value.data + return not self._state def close_cover(self): """Close the garage door.""" diff --git a/homeassistant/components/light/zwave.py b/homeassistant/components/light/zwave.py index 92c4e3f5d78..0c5cf1d081e 100644 --- a/homeassistant/components/light/zwave.py +++ b/homeassistant/components/light/zwave.py @@ -107,13 +107,12 @@ class ZwaveDimmer(zwave.ZWaveDeviceEntity, Light): _LOGGER.debug("AEOTEC ZW098 workaround enabled") self._zw098 = 1 - self.update_properties() - # Used for value change event handling self._refreshing = False self._timer = None _LOGGER.debug('self._refreshing=%s self.delay=%s', self._refresh_value, self._delay) + self.update_properties() def update_properties(self): """Update internal properties based on zwave values.""" diff --git a/homeassistant/components/lock/zwave.py b/homeassistant/components/lock/zwave.py index 6501c7d1b74..3b01138ccb2 100644 --- a/homeassistant/components/lock/zwave.py +++ b/homeassistant/components/lock/zwave.py @@ -234,11 +234,7 @@ class ZwaveLock(zwave.ZWaveDeviceEntity, LockDevice): def update_properties(self): """Callback on data changes for node values.""" - self._state = self.get_value(class_id=zwave - .const.COMMAND_CLASS_DOOR_LOCK, - type=zwave.const.TYPE_BOOL, - genre=zwave.const.GENRE_USER, - member='data') + self._state = self._value.data _LOGGER.debug('Lock state set from Bool value and' ' is %s', self._state) notification_data = self.get_value(class_id=zwave.const diff --git a/homeassistant/components/sensor/zwave.py b/homeassistant/components/sensor/zwave.py index b3f55efd779..e220825d526 100644 --- a/homeassistant/components/sensor/zwave.py +++ b/homeassistant/components/sensor/zwave.py @@ -53,6 +53,12 @@ class ZWaveSensor(zwave.ZWaveDeviceEntity): def __init__(self, value): """Initialize the sensor.""" 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 def force_update(self): @@ -62,12 +68,12 @@ class ZWaveSensor(zwave.ZWaveDeviceEntity): @property def state(self): """Return the state of the sensor.""" - return self._value.data + return self._state @property def unit_of_measurement(self): """Return the unit of measurement the value is expressed in.""" - return self._value.units + return self._units class ZWaveMultilevelSensor(ZWaveSensor): @@ -76,26 +82,22 @@ class ZWaveMultilevelSensor(ZWaveSensor): @property def state(self): """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 round(value, 1) - elif isinstance(value, float): - return round(value, 2) - - return value + return self._state @property def unit_of_measurement(self): """Return the unit the value is expressed in.""" - unit = self._value.units - - if unit == 'C': + if self._units == 'C': return TEMP_CELSIUS - elif unit == 'F': + elif self._units == 'F': return TEMP_FAHRENHEIT else: - return unit + return self._units class ZWaveAlarmSensor(ZWaveSensor): diff --git a/homeassistant/components/switch/zwave.py b/homeassistant/components/switch/zwave.py index fa50156ba4e..1a844ebcfe0 100644 --- a/homeassistant/components/switch/zwave.py +++ b/homeassistant/components/switch/zwave.py @@ -38,11 +38,16 @@ class ZwaveSwitch(zwave.ZWaveDeviceEntity, SwitchDevice): def __init__(self, value): """Initialize the Z-Wave switch device.""" 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 def is_on(self): """Return true if device is on.""" - return self._value.data + return self._state def turn_on(self, **kwargs): """Turn the device on.""" diff --git a/homeassistant/components/zwave/__init__.py b/homeassistant/components/zwave/__init__.py index 72ca67027d9..0ff33eb5975 100755 --- a/homeassistant/components/zwave/__init__.py +++ b/homeassistant/components/zwave/__init__.py @@ -262,22 +262,6 @@ def get_config_value(node, value_index, tries=5): 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 def setup(hass, config): """Setup Z-Wave. @@ -692,6 +676,7 @@ class ZWaveDeviceEntity(Entity): from pydispatch import dispatcher self._value = value self.entity_id = "{}.{}".format(domain, self._object_id()) + self._update_attributes() dispatcher.connect( self.network_value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) @@ -705,12 +690,28 @@ class ZWaveDeviceEntity(Entity): def value_changed(self, value): """Called when a value for this entity's node has changed.""" + self._update_attributes() self.update_properties() 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, 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: kwargs[CLASS_ID] = class_id _LOGGER.debug('method=%s, class_id=%s, index=%s, label=%s, data=%s,' @@ -746,7 +747,7 @@ class ZWaveDeviceEntity(Entity): return results 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) def set_value(self, **kwargs): @@ -785,26 +786,16 @@ class ZWaveDeviceEntity(Entity): def device_state_attributes(self): """Return the device specific state attributes.""" attrs = { - const.ATTR_NODE_ID: self._value.node.node_id, + const.ATTR_NODE_ID: self.node_id, } - try: - battery_level = self._value.node.get_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 self.battery_level is not None: + attrs[ATTR_BATTERY_LEVEL] = self.battery_level - if battery_level is not None: - attrs[ATTR_BATTERY_LEVEL] = battery_level + if self.location: + attrs[ATTR_LOCATION] = self.location - location = self._value.node.location - - if location: - attrs[ATTR_LOCATION] = location - - wakeup = _get_wakeup(self._value.node) - if wakeup: - attrs[ATTR_WAKEUP] = wakeup + if self.wakeup_interval is not None: + attrs[ATTR_WAKEUP] = self.wakeup_interval return attrs