From de027609d8696a15ff57ee3f13b3868ec63f058e Mon Sep 17 00:00:00 2001 From: Stefan Jonasson Date: Wed, 28 Oct 2015 12:27:58 +0100 Subject: [PATCH 1/5] Fixed entity_id for the script component. Alias now does not override the entity_id Fixed issue: #561 --- homeassistant/components/script.py | 5 +++-- homeassistant/helpers/entity_component.py | 6 ++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/script.py b/homeassistant/components/script.py index 3f892fdfa80..e5bfe61bfa5 100644 --- a/homeassistant/components/script.py +++ b/homeassistant/components/script.py @@ -75,7 +75,7 @@ def setup(hass, config): _LOGGER.warn("Missing key 'sequence' for script %s", name) continue alias = cfg.get(CONF_ALIAS, name) - script = Script(hass, alias, cfg[CONF_SEQUENCE]) + script = Script(hass, alias, name, cfg[CONF_SEQUENCE]) component.add_entities((script,)) _, object_id = split_entity_id(script.entity_id) hass.services.register(DOMAIN, object_id, service_handler) @@ -100,9 +100,10 @@ def setup(hass, config): class Script(ToggleEntity): """ Represents a script. """ - def __init__(self, hass, name, sequence): + def __init__(self, hass, name, entity_id, sequence): self.hass = hass self._name = name + self.entity_id = entity_id self.sequence = sequence self._lock = threading.Lock() self._cur = -1 diff --git a/homeassistant/helpers/entity_component.py b/homeassistant/helpers/entity_component.py index 708bf6e93a9..5223b7f0ca3 100644 --- a/homeassistant/helpers/entity_component.py +++ b/homeassistant/helpers/entity_component.py @@ -65,8 +65,10 @@ class EntityComponent(object): if entity is not None and entity not in self.entities.values(): entity.hass = self.hass - entity.entity_id = generate_entity_id( - self.entity_id_format, entity.name, self.entities.keys()) + if entity.entity_id is None: + entity.entity_id = generate_entity_id( + self.entity_id_format, entity.name, + self.entities.keys()) self.entities[entity.entity_id] = entity From 48bfc98acb45b0114ad7c004fc1aaa69ad823ab4 Mon Sep 17 00:00:00 2001 From: Stefan Jonasson Date: Wed, 28 Oct 2015 19:52:09 +0100 Subject: [PATCH 2/5] Fixed entity name --- homeassistant/components/script.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/script.py b/homeassistant/components/script.py index e5bfe61bfa5..9849a243a41 100644 --- a/homeassistant/components/script.py +++ b/homeassistant/components/script.py @@ -75,7 +75,8 @@ def setup(hass, config): _LOGGER.warn("Missing key 'sequence' for script %s", name) continue alias = cfg.get(CONF_ALIAS, name) - script = Script(hass, alias, name, cfg[CONF_SEQUENCE]) + entity_id = "{}.{}".format(DOMAIN, name) + script = Script(hass, alias, entity_id, cfg[CONF_SEQUENCE]) component.add_entities((script,)) _, object_id = split_entity_id(script.entity_id) hass.services.register(DOMAIN, object_id, service_handler) From 10c95b435250ccc7b754aa726153413238026ad7 Mon Sep 17 00:00:00 2001 From: Stefan Jonasson Date: Wed, 28 Oct 2015 20:17:17 +0100 Subject: [PATCH 3/5] Added pylint hint --- homeassistant/components/script.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/script.py b/homeassistant/components/script.py index 9849a243a41..084f5502426 100644 --- a/homeassistant/components/script.py +++ b/homeassistant/components/script.py @@ -99,6 +99,7 @@ def setup(hass, config): return True +# pylint: disable=too-many-instance-attributes class Script(ToggleEntity): """ Represents a script. """ def __init__(self, hass, name, entity_id, sequence): From f3500542dd85df362710aa921a5c2e2b777cb4cb Mon Sep 17 00:00:00 2001 From: Stefan Jonasson Date: Wed, 28 Oct 2015 20:17:17 +0100 Subject: [PATCH 4/5] Added pylint hint --- homeassistant/components/script.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/script.py b/homeassistant/components/script.py index 6d5f0ea37a1..a14919cab67 100644 --- a/homeassistant/components/script.py +++ b/homeassistant/components/script.py @@ -101,6 +101,7 @@ def setup(hass, config): return True +# pylint: disable=too-many-instance-attributes class Script(ToggleEntity): """ Represents a script. """ # pylint: disable=too-many-instance-attributes From 30de5af445772775401f894d76c0c8a095aed2c8 Mon Sep 17 00:00:00 2001 From: Stefan Jonasson Date: Wed, 28 Oct 2015 22:08:04 +0100 Subject: [PATCH 5/5] 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. """