mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Add Nuki Opener integration (#35702)
* Add Nuki Opener integration * Update pynuki version requirement; fix typo * Update requirements_all.txt * Create base class of shared lock and opener code * Clean up code formatting * Update requirements_all; Run isort * Remove unnecessary pass statements
This commit is contained in:
parent
2b3cf97979
commit
4f317353e0
@ -1,4 +1,5 @@
|
|||||||
"""Nuki.io lock platform."""
|
"""Nuki.io lock platform."""
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -50,9 +51,10 @@ LOCK_N_GO_SERVICE_SCHEMA = vol.Schema(
|
|||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the Nuki lock platform."""
|
"""Set up the Nuki lock platform."""
|
||||||
bridge = NukiBridge(
|
bridge = NukiBridge(
|
||||||
config[CONF_HOST], config[CONF_TOKEN], config[CONF_PORT], DEFAULT_TIMEOUT
|
config[CONF_HOST], config[CONF_TOKEN], config[CONF_PORT], DEFAULT_TIMEOUT,
|
||||||
)
|
)
|
||||||
devices = [NukiLock(lock) for lock in bridge.locks]
|
|
||||||
|
devices = [NukiLockEntity(lock) for lock in bridge.locks]
|
||||||
|
|
||||||
def service_handler(service):
|
def service_handler(service):
|
||||||
"""Service handler for nuki services."""
|
"""Service handler for nuki services."""
|
||||||
@ -65,41 +67,43 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
lock.lock_n_go(unlatch=unlatch)
|
lock.lock_n_go(unlatch=unlatch)
|
||||||
|
|
||||||
hass.services.register(
|
hass.services.register(
|
||||||
DOMAIN, SERVICE_LOCK_N_GO, service_handler, schema=LOCK_N_GO_SERVICE_SCHEMA
|
DOMAIN, SERVICE_LOCK_N_GO, service_handler, schema=LOCK_N_GO_SERVICE_SCHEMA,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
devices.extend([NukiOpenerEntity(opener) for opener in bridge.openers])
|
||||||
|
|
||||||
add_entities(devices)
|
add_entities(devices)
|
||||||
|
|
||||||
|
|
||||||
class NukiLock(LockEntity):
|
class NukiDeviceEntity(LockEntity, ABC):
|
||||||
"""Representation of a Nuki lock."""
|
"""Representation of a Nuki device."""
|
||||||
|
|
||||||
def __init__(self, nuki_lock):
|
def __init__(self, nuki_device):
|
||||||
"""Initialize the lock."""
|
"""Initialize the lock."""
|
||||||
self._nuki_lock = nuki_lock
|
self._nuki_device = nuki_device
|
||||||
self._available = nuki_lock.state not in ERROR_STATES
|
self._available = nuki_device.state not in ERROR_STATES
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of the lock."""
|
"""Return the name of the lock."""
|
||||||
return self._nuki_lock.name
|
return self._nuki_device.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_id(self) -> str:
|
def unique_id(self) -> str:
|
||||||
"""Return a unique ID."""
|
"""Return a unique ID."""
|
||||||
return self._nuki_lock.nuki_id
|
return self._nuki_device.nuki_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@abstractmethod
|
||||||
def is_locked(self):
|
def is_locked(self):
|
||||||
"""Return true if lock is locked."""
|
"""Return true if lock is locked."""
|
||||||
return self._nuki_lock.is_locked
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the device specific state attributes."""
|
"""Return the device specific state attributes."""
|
||||||
data = {
|
data = {
|
||||||
ATTR_BATTERY_CRITICAL: self._nuki_lock.battery_critical,
|
ATTR_BATTERY_CRITICAL: self._nuki_device.battery_critical,
|
||||||
ATTR_NUKI_ID: self._nuki_lock.nuki_id,
|
ATTR_NUKI_ID: self._nuki_device.nuki_id,
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@ -117,28 +121,49 @@ class NukiLock(LockEntity):
|
|||||||
"""Update the nuki lock properties."""
|
"""Update the nuki lock properties."""
|
||||||
for level in (False, True):
|
for level in (False, True):
|
||||||
try:
|
try:
|
||||||
self._nuki_lock.update(aggressive=level)
|
self._nuki_device.update(aggressive=level)
|
||||||
except RequestException:
|
except RequestException:
|
||||||
_LOGGER.warning("Network issues detect with %s", self.name)
|
_LOGGER.warning("Network issues detect with %s", self.name)
|
||||||
self._available = False
|
self._available = False
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# If in error state, we force an update and repoll data
|
# If in error state, we force an update and repoll data
|
||||||
self._available = self._nuki_lock.state not in ERROR_STATES
|
self._available = self._nuki_device.state not in ERROR_STATES
|
||||||
if self._available:
|
if self._available:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
def lock(self, **kwargs):
|
def lock(self, **kwargs):
|
||||||
"""Lock the device."""
|
"""Lock the device."""
|
||||||
self._nuki_lock.lock()
|
|
||||||
|
@abstractmethod
|
||||||
|
def unlock(self, **kwargs):
|
||||||
|
"""Unlock the device."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def open(self, **kwargs):
|
||||||
|
"""Open the door latch."""
|
||||||
|
|
||||||
|
|
||||||
|
class NukiLockEntity(NukiDeviceEntity):
|
||||||
|
"""Representation of a Nuki lock."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_locked(self):
|
||||||
|
"""Return true if lock is locked."""
|
||||||
|
return self._nuki_device.is_locked
|
||||||
|
|
||||||
|
def lock(self, **kwargs):
|
||||||
|
"""Lock the device."""
|
||||||
|
self._nuki_device.lock()
|
||||||
|
|
||||||
def unlock(self, **kwargs):
|
def unlock(self, **kwargs):
|
||||||
"""Unlock the device."""
|
"""Unlock the device."""
|
||||||
self._nuki_lock.unlock()
|
self._nuki_device.unlock()
|
||||||
|
|
||||||
def open(self, **kwargs):
|
def open(self, **kwargs):
|
||||||
"""Open the door latch."""
|
"""Open the door latch."""
|
||||||
self._nuki_lock.unlatch()
|
self._nuki_device.unlatch()
|
||||||
|
|
||||||
def lock_n_go(self, unlatch=False, **kwargs):
|
def lock_n_go(self, unlatch=False, **kwargs):
|
||||||
"""Lock and go.
|
"""Lock and go.
|
||||||
@ -146,4 +171,25 @@ class NukiLock(LockEntity):
|
|||||||
This will first unlock the door, then wait for 20 seconds (or another
|
This will first unlock the door, then wait for 20 seconds (or another
|
||||||
amount of time depending on the lock settings) and relock.
|
amount of time depending on the lock settings) and relock.
|
||||||
"""
|
"""
|
||||||
self._nuki_lock.lock_n_go(unlatch, kwargs)
|
self._nuki_device.lock_n_go(unlatch, kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class NukiOpenerEntity(NukiDeviceEntity):
|
||||||
|
"""Representation of a Nuki opener."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_locked(self):
|
||||||
|
"""Return true if ring-to-open is enabled."""
|
||||||
|
return not self._nuki_device.is_rto_activated
|
||||||
|
|
||||||
|
def lock(self, **kwargs):
|
||||||
|
"""Disable ring-to-open."""
|
||||||
|
self._nuki_device.deactivate_rto()
|
||||||
|
|
||||||
|
def unlock(self, **kwargs):
|
||||||
|
"""Enable ring-to-open."""
|
||||||
|
self._nuki_device.activate_rto()
|
||||||
|
|
||||||
|
def open(self, **kwargs):
|
||||||
|
"""Buzz open the door."""
|
||||||
|
self._nuki_device.electric_strike_actuation()
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
"domain": "nuki",
|
"domain": "nuki",
|
||||||
"name": "Nuki",
|
"name": "Nuki",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/nuki",
|
"documentation": "https://www.home-assistant.io/integrations/nuki",
|
||||||
"requirements": ["pynuki==1.3.3"],
|
"requirements": ["pynuki==1.3.7"],
|
||||||
"codeowners": ["@pvizeli"]
|
"codeowners": ["@pvizeli"]
|
||||||
}
|
}
|
||||||
|
@ -1486,7 +1486,7 @@ pynetgear==0.6.1
|
|||||||
pynetio==0.1.9.1
|
pynetio==0.1.9.1
|
||||||
|
|
||||||
# homeassistant.components.nuki
|
# homeassistant.components.nuki
|
||||||
pynuki==1.3.3
|
pynuki==1.3.7
|
||||||
|
|
||||||
# homeassistant.components.nut
|
# homeassistant.components.nut
|
||||||
pynut2==2.1.2
|
pynut2==2.1.2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user