From 30de5af445772775401f894d76c0c8a095aed2c8 Mon Sep 17 00:00:00 2001 From: Stefan Jonasson Date: Wed, 28 Oct 2015 22:08:04 +0100 Subject: [PATCH] Fix for Philio Zwave devices which don't send an off event. --- homeassistant/components/sensor/zwave.py | 63 +++++++++++++++++++++--- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/sensor/zwave.py b/homeassistant/components/sensor/zwave.py index 0cd136421a0..10d8734bcac 100644 --- a/homeassistant/components/sensor/zwave.py +++ b/homeassistant/components/sensor/zwave.py @@ -7,15 +7,27 @@ For more details about the zwave component, please refer to the documentation at https://home-assistant.io/components/zwave.html """ # pylint: disable=import-error +from homeassistant.helpers.event import track_point_in_time from openzwave.network import ZWaveNetwork from pydispatch import dispatcher - +import datetime +import homeassistant.util.dt as dt_util import homeassistant.components.zwave as zwave from homeassistant.helpers.entity import Entity from homeassistant.const import ( ATTR_BATTERY_LEVEL, STATE_ON, STATE_OFF, TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_LOCATION) +PHILIO = '013c' +PHILIO_SLIM_SENSOR = '0002' +PHILIO_SLIM_SENSOR_MOTION = (PHILIO, PHILIO_SLIM_SENSOR, 0) + +WORKAROUND_NO_TRIGGER_OFF_EVENT = 'trigger_no_off_event' + +SPECIFIC_DEVICE_MAPPINGS = [ + (WORKAROUND_NO_TRIGGER_OFF_EVENT, PHILIO_SLIM_SENSOR_MOTION), +] + def setup_platform(hass, config, add_devices, discovery_info=None): """ Sets up Z-Wave sensors. """ @@ -24,10 +36,17 @@ def setup_platform(hass, config, add_devices, discovery_info=None): value.set_change_verified(False) - # if 1 in groups and (zwave.NETWORK.controller.node_id not in - # groups[1].associations): - # node.groups[1].add_association(zwave.NETWORK.controller.node_id) + # Check workaround mappings for specific devices + for workaround_definition in SPECIFIC_DEVICE_MAPPINGS: + workaround, sensor_specification = workaround_definition + if sensor_specification == ( + value.command_class, value.node.manufacturer_id, + value.node.manufacturer_id, value.node.manufacturer_id): + if workaround == WORKAROUND_NO_TRIGGER_OFF_EVENT: + add_devices([ZWaveTriggerSensor(value, hass)]) + return + # generic Device mappings if value.command_class == zwave.COMMAND_CLASS_SENSOR_BINARY: add_devices([ZWaveBinarySensor(value)]) @@ -37,12 +56,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class ZWaveSensor(Entity): """ Represents a Z-Wave sensor. """ + def __init__(self, sensor_value): self._value = sensor_value self._node = sensor_value.node dispatcher.connect( - self._value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) + self.value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) @property def should_poll(self): @@ -90,7 +110,7 @@ class ZWaveSensor(Entity): def unit_of_measurement(self): return self._value.units - def _value_changed(self, value): + def value_changed(self, value): """ Called when a value has changed on the network. """ if self._value.value_id == value.value_id: self.update_ha_state() @@ -106,6 +126,37 @@ class ZWaveBinarySensor(ZWaveSensor): return STATE_ON if self._value.data else STATE_OFF +class ZWaveTriggerSensor(ZWaveSensor): + """ Represents a stateless sensor which triggers events within Z-Wave. """ + + def __init__(self, sensor_value, hass): + super(ZWaveTriggerSensor, self).__init__(sensor_value) + self._hass = hass + self.invalidate_after = None + + def value_changed(self, value): + """ Called when a value has changed on the network. """ + if self._value.value_id == value.value_id: + self.update_ha_state() + if value.data: + # only allow this value to be true for 60 secs + self.invalidate_after = dt_util.utcnow() + datetime.timedelta( + seconds=60) + track_point_in_time( + self._hass, self.update_ha_state, + self.invalidate_after) + + @property + def state(self): + """ Returns the state of the sensor. """ + if not self._value.data or \ + (self.invalidate_after is not None and + self.invalidate_after <= dt_util.utcnow()): + return STATE_OFF + + return STATE_ON + + class ZWaveMultilevelSensor(ZWaveSensor): """ Represents a multi level sensor Z-Wave sensor. """