core/homeassistant/components/lock/__init__.py

151 lines
4.0 KiB
Python
Raw Normal View History

"""Component to interface with locks that can be controlled remotely."""
from datetime import timedelta
import functools as ft
import logging
from typing import final
2016-04-13 02:01:53 +00:00
import voluptuous as vol
from homeassistant.const import (
2019-07-31 19:25:30 +00:00
ATTR_CODE,
ATTR_CODE_FORMAT,
SERVICE_LOCK,
SERVICE_OPEN,
SERVICE_UNLOCK,
STATE_LOCKED,
STATE_UNLOCKED,
2019-07-31 19:25:30 +00:00
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
PLATFORM_SCHEMA_BASE,
make_entity_service_schema,
)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
# mypy: allow-untyped-defs, no-check-untyped-defs
_LOGGER = logging.getLogger(__name__)
2019-07-31 19:25:30 +00:00
ATTR_CHANGED_BY = "changed_by"
2019-07-31 19:25:30 +00:00
DOMAIN = "lock"
SCAN_INTERVAL = timedelta(seconds=30)
2019-07-31 19:25:30 +00:00
ENTITY_ID_FORMAT = DOMAIN + ".{}"
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
LOCK_SERVICE_SCHEMA = make_entity_service_schema({vol.Optional(ATTR_CODE): cv.string})
2016-04-13 02:01:53 +00:00
# Bitfield of features supported by the lock entity
SUPPORT_OPEN = 1
2019-07-31 19:25:30 +00:00
PROP_TO_ATTR = {"changed_by": ATTR_CHANGED_BY, "code_format": ATTR_CODE_FORMAT}
async def async_setup(hass, config):
2016-02-28 11:03:47 +00:00
"""Track states and offer events for locks."""
component = hass.data[DOMAIN] = EntityComponent(
_LOGGER, DOMAIN, hass, SCAN_INTERVAL
2019-07-31 19:25:30 +00:00
)
await component.async_setup(config)
component.async_register_entity_service(
2019-07-31 19:25:30 +00:00
SERVICE_UNLOCK, LOCK_SERVICE_SCHEMA, "async_unlock"
)
component.async_register_entity_service(
2019-07-31 19:25:30 +00:00
SERVICE_LOCK, LOCK_SERVICE_SCHEMA, "async_lock"
)
component.async_register_entity_service(
2019-07-31 19:25:30 +00:00
SERVICE_OPEN, LOCK_SERVICE_SCHEMA, "async_open"
)
return True
async def async_setup_entry(hass, entry):
"""Set up a config entry."""
return await hass.data[DOMAIN].async_setup_entry(entry)
async def async_unload_entry(hass, entry):
"""Unload a config entry."""
return await hass.data[DOMAIN].async_unload_entry(entry)
class LockEntity(Entity):
"""Base class for lock entities."""
2016-03-07 21:13:18 +00:00
@property
def changed_by(self):
"""Last change triggered by."""
return None
@property
def code_format(self):
2016-02-28 11:03:47 +00:00
"""Regex for code format or None if no code is required."""
return None
@property
def is_locked(self):
2016-03-07 21:13:18 +00:00
"""Return true if the lock is locked."""
return None
def lock(self, **kwargs):
2016-03-07 21:13:18 +00:00
"""Lock the lock."""
raise NotImplementedError()
async def async_lock(self, **kwargs):
"""Lock the lock."""
await self.hass.async_add_executor_job(ft.partial(self.lock, **kwargs))
def unlock(self, **kwargs):
2016-03-07 21:13:18 +00:00
"""Unlock the lock."""
raise NotImplementedError()
async def async_unlock(self, **kwargs):
"""Unlock the lock."""
await self.hass.async_add_executor_job(ft.partial(self.unlock, **kwargs))
def open(self, **kwargs):
"""Open the door latch."""
raise NotImplementedError()
async def async_open(self, **kwargs):
"""Open the door latch."""
await self.hass.async_add_executor_job(ft.partial(self.open, **kwargs))
@final
@property
def state_attributes(self):
2016-02-28 11:03:47 +00:00
"""Return the state attributes."""
state_attr = {}
for prop, attr in PROP_TO_ATTR.items():
value = getattr(self, prop)
if value is not None:
state_attr[attr] = value
return state_attr
@property
def state(self):
2016-02-28 11:03:47 +00:00
"""Return the state."""
locked = self.is_locked
if locked is None:
return None
return STATE_LOCKED if locked else STATE_UNLOCKED
class LockDevice(LockEntity):
"""Representation of a lock (for backwards compatibility)."""
def __init_subclass__(cls, **kwargs):
"""Print deprecation warning."""
super().__init_subclass__(**kwargs)
_LOGGER.warning(
2020-08-27 11:56:20 +00:00
"LockDevice is deprecated, modify %s to extend LockEntity",
cls.__name__,
)