From 8bf0beff49d56c6473637eaaef634d7faa6dc0c0 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 12 Oct 2018 21:05:41 -0400 Subject: [PATCH 1/3] Add workaround to use notification state for zwave lock state There are several zwave lock models out there which do not seem to update the lock state on non-rf events (see #11934 #14632 #14534 for examples) including kwikset smartkey zwave plus locks (which I own). In these cases it seems that the notifications for non-rf events the access_control value is updated but not the primary value for the lock state, which is what is used to set the is_locked property. To properly have the lock state accurate for all types of notifications on these models we need to use the access_control field. This commit adds a workaround for the 4 models reported to exhibit this behavior so that home-assistant will reliably set the lock state for all device notifications. --- homeassistant/components/lock/zwave.py | 36 ++++++++++++++++++++++++-- tests/components/lock/test_zwave.py | 16 ++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/lock/zwave.py b/homeassistant/components/lock/zwave.py index 4a2b71f0b48f5..e1ee16c1d7d81 100644 --- a/homeassistant/components/lock/zwave.py +++ b/homeassistant/components/lock/zwave.py @@ -28,9 +28,34 @@ DANALOCK_V2_BTZE = 0x2 POLYCONTROL_DANALOCK_V2_BTZE_LOCK = (POLYCONTROL, DANALOCK_V2_BTZE) WORKAROUND_V2BTZE = 'v2btze' +WORKAROUND_DEVICE_STATE = 'state' +# Kwikset 914TRL ZW500 +KWIKSET = 0x0090 +ZW500_914TRL = 0x440 +KWIKSET_914TRL_ZW500 = (KWIKSET, ZW500_914TRL) +# Yale YRD210 +YALE = 0x0129 +YRD210 = 0x0209 +YRD210_A = 0xAA00 +YRD210_B = 0x0000 +YALE_YRD210 = (YALE, YRD210) +YALE_YRD210_A = (YALE, YRD210_A) +YALE_YRD210_B = (YALE, YRD210_B) +# Schalge BE469 and FE599NX +SCHLAGE = 0x003B +BE469 = 0x5044 +SCHLAGE_BE469 = (SCHLAGE, BE469) +FE599NX = 0x504C +SCLAGE_FE599NX = (SCHLAGE, FE599NX) DEVICE_MAPPINGS = { - POLYCONTROL_DANALOCK_V2_BTZE_LOCK: WORKAROUND_V2BTZE + POLYCONTROL_DANALOCK_V2_BTZE_LOCK: WORKAROUND_V2BTZE, + KWIKSET_914TRL_ZW500: WORKAROUND_DEVICE_STATE, + YALE_YRD210: WORKAROUND_DEVICE_STATE, + YALE_YRD210_A: WORKAROUND_DEVICE_STATE, + YALE_YRD210_B: WORKAROUND_DEVICE_STATE, + SCHLAGE_BE469: WORKAROUND_DEVICE_STATE, + SCLAGE_FE599NX: WORKAROUND_DEVICE_STATE, } LOCK_NOTIFICATION = { @@ -204,6 +229,7 @@ def __init__(self, values): self._notification = None self._lock_status = None self._v2btze = None + self._state_workaround = False # Enable appropriate workaround flags for our device # Make sure that we have values for the key before converting to int @@ -216,6 +242,11 @@ def __init__(self, values): self._v2btze = 1 _LOGGER.debug("Polycontrol Danalock v2 BTZE " "workaround enabled") + if DEVICE_MAPPINGS[specific_sensor_key] == \ + WORKAROUND_DEVICE_STATE: + self._state_workaround = True + _LOGGER.debug( + "Notification device state workaround enabled") self.update_properties() def update_properties(self): @@ -225,7 +256,8 @@ def update_properties(self): if self.values.access_control: notification_data = self.values.access_control.data self._notification = LOCK_NOTIFICATION.get(str(notification_data)) - + if self._state_workaround: + self._state = LOCK_STATUS.get(str(notification_data)) if self._v2btze: if self.values.v2btze_advanced and \ self.values.v2btze_advanced.data == CONFIG_ADVANCED: diff --git a/tests/components/lock/test_zwave.py b/tests/components/lock/test_zwave.py index 83aec7f0ce97e..89ce034d4450a 100644 --- a/tests/components/lock/test_zwave.py +++ b/tests/components/lock/test_zwave.py @@ -63,6 +63,22 @@ def test_lock_value_changed(mock_openzwave): assert device.is_locked +def test_lock_value_changed_workaround(mock_openzwave): + """Test value changed for Z-Wave lock using notification state.""" + node = MockNode(manufacturer_id='0090', product_id='0440') + values = MockEntityValues( + primary=MockValue(data=True, node=node), + access_control=MockValue(data=1, node=node), + alarm_type=None, + alarm_level=None, + ) + device = zwave.get_device(node=node, values=values) + assert device.is_locked + values.access_control.data = 2 + value_changed(values.access_control) + assert not device.is_locked + + def test_v2btze_value_changed(mock_openzwave): """Test value changed for v2btze Z-Wave lock.""" node = MockNode(manufacturer_id='010e', product_id='0002') From 21aa6de88afcda710dd6e2b62b3038b2f76faeb8 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Sun, 4 Nov 2018 19:54:55 -0500 Subject: [PATCH 2/3] Add YRD220 as per adrum to workaround list --- homeassistant/components/lock/zwave.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/homeassistant/components/lock/zwave.py b/homeassistant/components/lock/zwave.py index e1ee16c1d7d81..e31b0b642d674 100644 --- a/homeassistant/components/lock/zwave.py +++ b/homeassistant/components/lock/zwave.py @@ -41,6 +41,8 @@ YALE_YRD210 = (YALE, YRD210) YALE_YRD210_A = (YALE, YRD210_A) YALE_YRD210_B = (YALE, YRD210_B) +# Yale YRD220 (as reported by adrum in PR #17386) +YALE_YRD220 = (0x0109, 0x0000) # Schalge BE469 and FE599NX SCHLAGE = 0x003B BE469 = 0x5044 @@ -54,6 +56,7 @@ YALE_YRD210: WORKAROUND_DEVICE_STATE, YALE_YRD210_A: WORKAROUND_DEVICE_STATE, YALE_YRD210_B: WORKAROUND_DEVICE_STATE, + YALE_YRD220: WORKAROUND_DEVICE_STATE, SCHLAGE_BE469: WORKAROUND_DEVICE_STATE, SCLAGE_FE599NX: WORKAROUND_DEVICE_STATE, } From b31996287930229393e518e7deb06a2f259fc415 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Mon, 5 Nov 2018 13:31:33 -0500 Subject: [PATCH 3/3] Inline constants --- homeassistant/components/lock/zwave.py | 39 ++++++++------------------ 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/homeassistant/components/lock/zwave.py b/homeassistant/components/lock/zwave.py index e31b0b642d674..2ea8300fb9a4a 100644 --- a/homeassistant/components/lock/zwave.py +++ b/homeassistant/components/lock/zwave.py @@ -29,36 +29,21 @@ POLYCONTROL_DANALOCK_V2_BTZE_LOCK = (POLYCONTROL, DANALOCK_V2_BTZE) WORKAROUND_V2BTZE = 'v2btze' WORKAROUND_DEVICE_STATE = 'state' -# Kwikset 914TRL ZW500 -KWIKSET = 0x0090 -ZW500_914TRL = 0x440 -KWIKSET_914TRL_ZW500 = (KWIKSET, ZW500_914TRL) -# Yale YRD210 -YALE = 0x0129 -YRD210 = 0x0209 -YRD210_A = 0xAA00 -YRD210_B = 0x0000 -YALE_YRD210 = (YALE, YRD210) -YALE_YRD210_A = (YALE, YRD210_A) -YALE_YRD210_B = (YALE, YRD210_B) -# Yale YRD220 (as reported by adrum in PR #17386) -YALE_YRD220 = (0x0109, 0x0000) -# Schalge BE469 and FE599NX -SCHLAGE = 0x003B -BE469 = 0x5044 -SCHLAGE_BE469 = (SCHLAGE, BE469) -FE599NX = 0x504C -SCLAGE_FE599NX = (SCHLAGE, FE599NX) DEVICE_MAPPINGS = { POLYCONTROL_DANALOCK_V2_BTZE_LOCK: WORKAROUND_V2BTZE, - KWIKSET_914TRL_ZW500: WORKAROUND_DEVICE_STATE, - YALE_YRD210: WORKAROUND_DEVICE_STATE, - YALE_YRD210_A: WORKAROUND_DEVICE_STATE, - YALE_YRD210_B: WORKAROUND_DEVICE_STATE, - YALE_YRD220: WORKAROUND_DEVICE_STATE, - SCHLAGE_BE469: WORKAROUND_DEVICE_STATE, - SCLAGE_FE599NX: WORKAROUND_DEVICE_STATE, + # Kwikset 914TRL ZW500 + (0x0090, 0x440): WORKAROUND_DEVICE_STATE, + # Yale YRD210 + (0x0129, 0x0209): WORKAROUND_DEVICE_STATE, + (0x0129, 0xAA00): WORKAROUND_DEVICE_STATE, + (0x0129, 0x0000): WORKAROUND_DEVICE_STATE, + # Yale YRD220 (as reported by adrum in PR #17386) + (0x0109, 0x0000): WORKAROUND_DEVICE_STATE, + # Schlage BE469 + (0x003B, 0x5044): WORKAROUND_DEVICE_STATE, + # Schlage FE599NX + (0x003B, 0x504C): WORKAROUND_DEVICE_STATE, } LOCK_NOTIFICATION = {