[lock.zwave] Add set, get and clear usercodes for zwave locks (#5489)

* Add set, get and clear usercodes for zwave locks

* Fix CRLF
This commit is contained in:
John Arild Berentsen 2017-01-27 06:45:04 +01:00 committed by Paulus Schoutsen
parent 295a232374
commit d0538fe3aa
2 changed files with 153 additions and 22 deletions

View File

@ -1,3 +1,25 @@
clear_usercode:
description: Clear a usercode from lock
fields:
node_id:
description: Node id of the lock
example: 18
code_slot:
description: Code slot to clear code from
example: 1
get_usercode:
description: Retrieve a usercode from lock
fields:
node_id:
description: Node id of the lock
example: 18
code_slot:
description: Code slot to retrive a code from
example: 1
lock: lock:
description: Lock all or specified locks description: Lock all or specified locks
@ -9,6 +31,20 @@ lock:
description: An optional code to lock the lock with description: An optional code to lock the lock with
example: 1234 example: 1234
set_usercode:
description: Set a usercode to lock
fields:
node_id:
description: Node id of the lock
example: 18
code_slot:
description: Code slot to set the code
example: 1
usercode:
description: Code to set
example: 1234
unlock: unlock:
description: Unlock all or specified locks description: Unlock all or specified locks

View File

@ -7,14 +7,25 @@ https://home-assistant.io/components/lock.zwave/
# Because we do not compile openzwave on CI # Because we do not compile openzwave on CI
# pylint: disable=import-error # pylint: disable=import-error
import logging import logging
from os import path
import voluptuous as vol
from homeassistant.components.lock import DOMAIN, LockDevice from homeassistant.components.lock import DOMAIN, LockDevice
from homeassistant.components import zwave from homeassistant.components import zwave
from homeassistant.config import load_yaml_config_file
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ATTR_NOTIFICATION = 'notification' ATTR_NOTIFICATION = 'notification'
ATTR_LOCK_STATUS = 'lock_status' ATTR_LOCK_STATUS = 'lock_status'
ATTR_CODE_SLOT = 'code_slot'
ATTR_USERCODE = 'usercode'
SERVICE_SET_USERCODE = 'set_usercode'
SERVICE_GET_USERCODE = 'get_usercode'
SERVICE_CLEAR_USERCODE = 'clear_usercode'
LOCK_NOTIFICATION = { LOCK_NOTIFICATION = {
1: 'Manual Lock', 1: 'Manual Lock',
2: 'Manual Unlock', 2: 'Manual Unlock',
@ -80,6 +91,22 @@ ALARM_TYPE_STD = [
113 113
] ]
SET_USERCODE_SCHEMA = vol.Schema({
vol.Required(zwave.const.ATTR_NODE_ID): vol.Coerce(int),
vol.Required(ATTR_CODE_SLOT): vol.Coerce(int),
vol.Required(ATTR_USERCODE): vol.Coerce(int),
})
GET_USERCODE_SCHEMA = vol.Schema({
vol.Required(zwave.const.ATTR_NODE_ID): vol.Coerce(int),
vol.Required(ATTR_CODE_SLOT): vol.Coerce(int),
})
CLEAR_USERCODE_SCHEMA = vol.Schema({
vol.Required(zwave.const.ATTR_NODE_ID): vol.Coerce(int),
vol.Required(ATTR_CODE_SLOT): vol.Coerce(int),
})
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
@ -90,13 +117,81 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]] node = zwave.NETWORK.nodes[discovery_info[zwave.const.ATTR_NODE_ID]]
value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]] value = node.values[discovery_info[zwave.const.ATTR_VALUE_ID]]
descriptions = load_yaml_config_file(
path.join(path.dirname(__file__), 'services.yaml'))
def set_usercode(service):
"""Set the usercode to index X on the lock."""
node_id = service.data.get(zwave.const.ATTR_NODE_ID)
lock_node = zwave.NETWORK.nodes[node_id]
code_slot = service.data.get(ATTR_CODE_SLOT)
usercode = service.data.get(ATTR_USERCODE)
for value in lock_node.get_values(
class_id=zwave.const.COMMAND_CLASS_USER_CODE).values():
if value.index != code_slot:
continue
if len(str(usercode)) > 4:
_LOGGER.error('Invalid code provided: (%s)'
' usercode must %s or less digits',
usercode, len(value.data))
value.data = str(usercode)
break
def get_usercode(service):
"""Get a usercode at index X on the lock."""
node_id = service.data.get(zwave.const.ATTR_NODE_ID)
lock_node = zwave.NETWORK.nodes[node_id]
code_slot = service.data.get(ATTR_CODE_SLOT)
for value in lock_node.get_values(
class_id=zwave.const.COMMAND_CLASS_USER_CODE).values():
if value.index != code_slot:
continue
_LOGGER.info('Usercode at slot %s is: %s', value.index, value.data)
break
def clear_usercode(service):
"""Set usercode to slot X on the lock."""
node_id = service.data.get(zwave.const.ATTR_NODE_ID)
lock_node = zwave.NETWORK.nodes[node_id]
code_slot = service.data.get(ATTR_CODE_SLOT)
data = ''
for value in lock_node.get_values(
class_id=zwave.const.COMMAND_CLASS_USER_CODE).values():
if value.index != code_slot:
continue
for i in range(len(value.data)):
data += '\0'
i += 1
_LOGGER.debug('Data to clear lock: %s', data)
value.data = data
_LOGGER.info('Usercode at slot %s is cleared', value.index)
break
if value.command_class != zwave.const.COMMAND_CLASS_DOOR_LOCK: if value.command_class != zwave.const.COMMAND_CLASS_DOOR_LOCK:
return return
if value.type != zwave.const.TYPE_BOOL: if value.type != zwave.const.TYPE_BOOL:
return return
if value.genre != zwave.const.GENRE_USER: if value.genre != zwave.const.GENRE_USER:
return return
if node.has_command_class(zwave.const.COMMAND_CLASS_USER_CODE):
hass.services.register(DOMAIN,
SERVICE_SET_USERCODE,
set_usercode,
descriptions.get(SERVICE_SET_USERCODE),
schema=SET_USERCODE_SCHEMA)
hass.services.register(DOMAIN,
SERVICE_GET_USERCODE,
get_usercode,
descriptions.get(SERVICE_GET_USERCODE),
schema=GET_USERCODE_SCHEMA)
hass.services.register(DOMAIN,
SERVICE_CLEAR_USERCODE,
clear_usercode,
descriptions.get(SERVICE_CLEAR_USERCODE),
schema=CLEAR_USERCODE_SCHEMA)
value.set_change_verified(False) value.set_change_verified(False)
add_devices([ZwaveLock(value)]) add_devices([ZwaveLock(value)])