From 41ee798b0f12b876cb7f7aac2f1b463710d668b3 Mon Sep 17 00:00:00 2001 From: John Arild Berentsen Date: Fri, 20 Jan 2017 22:01:36 +0100 Subject: [PATCH] [WIP][ZWave][Lock] Further improvements to zwave lock platform (#5400) * Further improvements to zwave lock platform * Add missing notification * Some improvements --- homeassistant/components/lock/zwave.py | 103 ++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/lock/zwave.py b/homeassistant/components/lock/zwave.py index 17fc30e93cf..9dbbb8e733f 100644 --- a/homeassistant/components/lock/zwave.py +++ b/homeassistant/components/lock/zwave.py @@ -14,7 +14,7 @@ from homeassistant.components import zwave _LOGGER = logging.getLogger(__name__) ATTR_NOTIFICATION = 'notification' - +ATTR_LOCK_STATUS = 'lock_status' LOCK_NOTIFICATION = { 1: 'Manual Lock', 2: 'Manual Unlock', @@ -22,18 +22,64 @@ LOCK_NOTIFICATION = { 4: 'RF Unlock', 5: 'Keypad Lock', 6: 'Keypad Unlock', + 11: 'Lock Jammed', 254: 'Unknown Event' } +LOCK_ALARM_TYPE = { + 9: 'Deadbolt Jammed', + 18: 'Locked with Keypad by user', + 19: 'Unlocked with Keypad by user ', + 21: 'Manually Locked by', + 22: 'Manually Unlocked by Key or Inside thumb turn', + 24: 'Locked by RF', + 25: 'Unlocked by RF', + 27: 'Auto re-lock', + 33: 'User deleted: ', + 112: 'Master code changed or User added: ', + 113: 'Duplicate Pin-code: ', + 130: 'RF module, power restored', + 161: 'Tamper Alarm: ', + 167: 'Low Battery', + 168: 'Critical Battery Level', + 169: 'Battery too low to operate' +} + +MANUAL_LOCK_ALARM_LEVEL = { + 1: 'Key Cylinder or Inside thumb turn', + 2: 'Touch function (lock and leave)' +} + +TAMPER_ALARM_LEVEL = { + 1: 'Too many keypresses', + 2: 'Cover removed' +} + LOCK_STATUS = { 1: True, 2: False, 3: True, 4: False, 5: True, - 6: False + 6: False, + 9: False, + 18: True, + 19: False, + 21: True, + 22: False, + 24: True, + 25: False, + 27: True } +ALARM_TYPE_STD = [ + 18, + 19, + 33, + 112, + 113 +] + # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): @@ -68,6 +114,7 @@ class ZwaveLock(zwave.ZWaveDeviceEntity, LockDevice): self._node = value.node self._state = None self._notification = None + self._lock_status = None dispatcher.connect( self._value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED) self.update_properties() @@ -89,9 +136,55 @@ class ZwaveLock(zwave.ZWaveDeviceEntity, LockDevice): self._notification = LOCK_NOTIFICATION.get(value.data) if self._notification: self._state = LOCK_STATUS.get(value.data) + _LOGGER.debug('Lock state set from Access Control value and' + ' is %s', value.data) break - if not self._notification: - self._state = self._value.data + + for value in self._node.get_values( + class_id=zwave.const.COMMAND_CLASS_ALARM).values(): + if value.label != "Alarm Type": + continue + alarm_type = LOCK_ALARM_TYPE.get(value.data) + if alarm_type: + self._state = LOCK_STATUS.get(value.data) + _LOGGER.debug('Lock state set from Alarm Type value and' + ' is %s', value.data) + break + + for value in self._node.get_values( + class_id=zwave.const.COMMAND_CLASS_ALARM).values(): + if value.label != "Alarm Level": + continue + alarm_level = value.data + _LOGGER.debug('Lock alarm_level is %s', alarm_level) + if alarm_type is 21: + self._lock_status = '{}{}'.format( + LOCK_ALARM_TYPE.get(alarm_type), + MANUAL_LOCK_ALARM_LEVEL.get(alarm_level)) + if alarm_type in ALARM_TYPE_STD: + self._lock_status = '{}{}'.format( + LOCK_ALARM_TYPE.get(alarm_type), alarm_level) + break + if alarm_type is 161: + self._lock_status = '{}{}'.format( + LOCK_ALARM_TYPE.get(alarm_type), + TAMPER_ALARM_LEVEL.get(alarm_level)) + break + if alarm_type != 0: + self._lock_status = LOCK_ALARM_TYPE.get(alarm_type) + break + + if not self._notification and not self._lock_status: + for value in self._node.get_values( + class_id=zwave.const.COMMAND_CLASS_DOOR_LOCK).values(): + if value.type != zwave.const.TYPE_BOOL: + continue + if value.genre != zwave.const.GENRE_USER: + continue + self._state = value.data + _LOGGER.debug('Lock state set from Bool value and' + ' is %s', value.data) + break @property def is_locked(self): @@ -112,4 +205,6 @@ class ZwaveLock(zwave.ZWaveDeviceEntity, LockDevice): data = super().device_state_attributes if self._notification: data[ATTR_NOTIFICATION] = self._notification + if self._lock_status: + data[ATTR_LOCK_STATUS] = self._lock_status return data