Add nuki lock'n'go and unlatch services and add attributes (#8687)
* Add lock'n'go service * Add unlatch service * Implement changes requested by @MartinHjelmare * Fix service domain
This commit is contained in:
parent
e81b3f7bc0
commit
3aceca9d8a
3 changed files with 102 additions and 6 deletions
|
@ -4,28 +4,47 @@ Nuki.io lock platform.
|
||||||
For more details about this platform, please refer to the documentation
|
For more details about this platform, please refer to the documentation
|
||||||
https://home-assistant.io/components/lock.nuki/
|
https://home-assistant.io/components/lock.nuki/
|
||||||
"""
|
"""
|
||||||
|
import asyncio
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
from os import path
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.components.lock import (LockDevice, PLATFORM_SCHEMA)
|
from homeassistant.components.lock import (DOMAIN, LockDevice, PLATFORM_SCHEMA)
|
||||||
from homeassistant.const import (CONF_HOST, CONF_PORT, CONF_TOKEN)
|
from homeassistant.config import load_yaml_config_file
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.const import (
|
||||||
|
ATTR_ENTITY_ID, CONF_HOST, CONF_PORT, CONF_TOKEN)
|
||||||
|
from homeassistant.helpers.service import extract_entity_ids
|
||||||
|
|
||||||
REQUIREMENTS = ['pynuki==1.2.2']
|
REQUIREMENTS = ['pynuki==1.3.1']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_PORT = 8080
|
DEFAULT_PORT = 8080
|
||||||
|
|
||||||
|
ATTR_BATTERY_CRITICAL = 'battery_critical'
|
||||||
|
ATTR_NUKI_ID = 'nuki_id'
|
||||||
|
ATTR_UNLATCH = 'unlatch'
|
||||||
|
NUKI_DATA = 'nuki'
|
||||||
|
SERVICE_LOCK_N_GO = 'nuki_lock_n_go'
|
||||||
|
SERVICE_UNLATCH = 'nuki_unlatch'
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_HOST): cv.string,
|
vol.Required(CONF_HOST): cv.string,
|
||||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
||||||
vol.Required(CONF_TOKEN): cv.string
|
vol.Required(CONF_TOKEN): cv.string
|
||||||
})
|
})
|
||||||
|
|
||||||
|
LOCK_N_GO_SERVICE_SCHEMA = vol.Schema({
|
||||||
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
|
||||||
|
vol.Optional(ATTR_UNLATCH, default=False): cv.boolean
|
||||||
|
})
|
||||||
|
|
||||||
|
UNLATCH_SERVICE_SCHEMA = vol.Schema({
|
||||||
|
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids
|
||||||
|
})
|
||||||
|
|
||||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=30)
|
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=30)
|
||||||
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=5)
|
MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(seconds=5)
|
||||||
|
@ -38,6 +57,34 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
bridge = NukiBridge(config.get(CONF_HOST), config.get(CONF_TOKEN))
|
bridge = NukiBridge(config.get(CONF_HOST), config.get(CONF_TOKEN))
|
||||||
add_devices([NukiLock(lock) for lock in bridge.locks])
|
add_devices([NukiLock(lock) for lock in bridge.locks])
|
||||||
|
|
||||||
|
def service_handler(service):
|
||||||
|
"""Service handler for nuki services."""
|
||||||
|
entity_ids = extract_entity_ids(hass, service)
|
||||||
|
all_locks = hass.data[NUKI_DATA][DOMAIN]
|
||||||
|
target_locks = []
|
||||||
|
if not entity_ids:
|
||||||
|
target_locks = all_locks
|
||||||
|
else:
|
||||||
|
for lock in all_locks:
|
||||||
|
if lock.entity_id in entity_ids:
|
||||||
|
target_locks.append(lock)
|
||||||
|
for lock in target_locks:
|
||||||
|
if service.service == SERVICE_LOCK_N_GO:
|
||||||
|
unlatch = service.data[ATTR_UNLATCH]
|
||||||
|
lock.lock_n_go(unlatch=unlatch)
|
||||||
|
elif service.service == SERVICE_UNLATCH:
|
||||||
|
lock.unlatch()
|
||||||
|
|
||||||
|
descriptions = load_yaml_config_file(
|
||||||
|
path.join(path.dirname(__file__), 'services.yaml'))
|
||||||
|
|
||||||
|
hass.services.register(
|
||||||
|
DOMAIN, SERVICE_LOCK_N_GO, service_handler,
|
||||||
|
descriptions.get(SERVICE_LOCK_N_GO), schema=LOCK_N_GO_SERVICE_SCHEMA)
|
||||||
|
hass.services.register(
|
||||||
|
DOMAIN, SERVICE_UNLATCH, service_handler,
|
||||||
|
descriptions.get(SERVICE_UNLATCH), schema=UNLATCH_SERVICE_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
class NukiLock(LockDevice):
|
class NukiLock(LockDevice):
|
||||||
"""Representation of a Nuki lock."""
|
"""Representation of a Nuki lock."""
|
||||||
|
@ -47,6 +94,16 @@ class NukiLock(LockDevice):
|
||||||
self._nuki_lock = nuki_lock
|
self._nuki_lock = nuki_lock
|
||||||
self._locked = nuki_lock.is_locked
|
self._locked = nuki_lock.is_locked
|
||||||
self._name = nuki_lock.name
|
self._name = nuki_lock.name
|
||||||
|
self._battery_critical = nuki_lock.battery_critical
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_added_to_hass(self):
|
||||||
|
"""Callback when entity is added to hass."""
|
||||||
|
if NUKI_DATA not in self.hass.data:
|
||||||
|
self.hass.data[NUKI_DATA] = {}
|
||||||
|
if DOMAIN not in self.hass.data[NUKI_DATA]:
|
||||||
|
self.hass.data[NUKI_DATA][DOMAIN] = []
|
||||||
|
self.hass.data[NUKI_DATA][DOMAIN].append(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -58,12 +115,20 @@ class NukiLock(LockDevice):
|
||||||
"""Return true if lock is locked."""
|
"""Return true if lock is locked."""
|
||||||
return self._locked
|
return self._locked
|
||||||
|
|
||||||
@Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS)
|
@property
|
||||||
|
def device_state_attributes(self):
|
||||||
|
"""Return the device specific state attributes."""
|
||||||
|
data = {
|
||||||
|
ATTR_BATTERY_CRITICAL: self._battery_critical,
|
||||||
|
ATTR_NUKI_ID: self._nuki_lock.nuki_id}
|
||||||
|
return data
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Update the nuki lock properties."""
|
"""Update the nuki lock properties."""
|
||||||
self._nuki_lock.update(aggressive=False)
|
self._nuki_lock.update(aggressive=False)
|
||||||
self._name = self._nuki_lock.name
|
self._name = self._nuki_lock.name
|
||||||
self._locked = self._nuki_lock.is_locked
|
self._locked = self._nuki_lock.is_locked
|
||||||
|
self._battery_critical = self._nuki_lock.battery_critical
|
||||||
|
|
||||||
def lock(self, **kwargs):
|
def lock(self, **kwargs):
|
||||||
"""Lock the device."""
|
"""Lock the device."""
|
||||||
|
@ -72,3 +137,15 @@ class NukiLock(LockDevice):
|
||||||
def unlock(self, **kwargs):
|
def unlock(self, **kwargs):
|
||||||
"""Unlock the device."""
|
"""Unlock the device."""
|
||||||
self._nuki_lock.unlock()
|
self._nuki_lock.unlock()
|
||||||
|
|
||||||
|
def lock_n_go(self, unlatch=False, **kwargs):
|
||||||
|
"""Lock and go.
|
||||||
|
|
||||||
|
This will first unlock the door, then wait for 20 seconds (or another
|
||||||
|
amount of time depending on the lock settings) and relock.
|
||||||
|
"""
|
||||||
|
self._nuki_lock.lock_n_go(unlatch, kwargs)
|
||||||
|
|
||||||
|
def unlatch(self, **kwargs):
|
||||||
|
"""Unlatch door."""
|
||||||
|
self._nuki_lock.unlatch()
|
||||||
|
|
|
@ -20,6 +20,25 @@ get_usercode:
|
||||||
description: Code slot to retrive a code from
|
description: Code slot to retrive a code from
|
||||||
example: 1
|
example: 1
|
||||||
|
|
||||||
|
nuki_lock_n_go:
|
||||||
|
description: "Lock 'n' Go"
|
||||||
|
|
||||||
|
fields:
|
||||||
|
entity_id:
|
||||||
|
description: Entity id of the Nuki lock
|
||||||
|
example: 'lock.front_door'
|
||||||
|
unlatch:
|
||||||
|
description: Whether to unlatch the lock
|
||||||
|
example: false
|
||||||
|
|
||||||
|
nuki_unlatch:
|
||||||
|
description: "Unlatch"
|
||||||
|
|
||||||
|
fields:
|
||||||
|
entity_id:
|
||||||
|
description: Entity id of the Nuki lock
|
||||||
|
example: 'lock.front_door'
|
||||||
|
|
||||||
lock:
|
lock:
|
||||||
description: Lock all or specified locks
|
description: Lock all or specified locks
|
||||||
|
|
||||||
|
|
|
@ -658,7 +658,7 @@ pynetgear==0.3.3
|
||||||
pynetio==0.1.6
|
pynetio==0.1.6
|
||||||
|
|
||||||
# homeassistant.components.lock.nuki
|
# homeassistant.components.lock.nuki
|
||||||
pynuki==1.2.2
|
pynuki==1.3.1
|
||||||
|
|
||||||
# homeassistant.components.sensor.nut
|
# homeassistant.components.sensor.nut
|
||||||
pynut2==2.1.2
|
pynut2==2.1.2
|
||||||
|
|
Loading…
Add table
Reference in a new issue