2022-01-11 19:20:15 +00:00
|
|
|
"""Lock for Yale Alarm."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
|
|
|
|
from yalesmartalarmclient.exceptions import AuthenticationError, UnknownError
|
|
|
|
|
|
|
|
from homeassistant.components.lock import LockEntity
|
|
|
|
from homeassistant.config_entries import ConfigEntry
|
2022-01-13 09:34:43 +00:00
|
|
|
from homeassistant.const import ATTR_CODE, CONF_CODE
|
2022-01-11 19:20:15 +00:00
|
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
|
|
|
|
from .const import (
|
|
|
|
CONF_LOCK_CODE_DIGITS,
|
|
|
|
COORDINATOR,
|
|
|
|
DEFAULT_LOCK_CODE_DIGITS,
|
|
|
|
DOMAIN,
|
|
|
|
LOGGER,
|
|
|
|
)
|
|
|
|
from .coordinator import YaleDataUpdateCoordinator
|
2022-01-13 09:34:43 +00:00
|
|
|
from .entity import YaleEntity
|
2022-01-11 19:20:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def async_setup_entry(
|
|
|
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
|
|
|
) -> None:
|
|
|
|
"""Set up the Yale lock entry."""
|
|
|
|
|
|
|
|
coordinator: YaleDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][
|
|
|
|
COORDINATOR
|
|
|
|
]
|
|
|
|
code_format = entry.options.get(CONF_LOCK_CODE_DIGITS, DEFAULT_LOCK_CODE_DIGITS)
|
|
|
|
|
|
|
|
async_add_entities(
|
|
|
|
YaleDoorlock(coordinator, data, code_format)
|
|
|
|
for data in coordinator.data["locks"]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2022-01-13 09:34:43 +00:00
|
|
|
class YaleDoorlock(YaleEntity, LockEntity):
|
2022-01-11 19:20:15 +00:00
|
|
|
"""Representation of a Yale doorlock."""
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self, coordinator: YaleDataUpdateCoordinator, data: dict, code_format: int
|
|
|
|
) -> None:
|
|
|
|
"""Initialize the Yale Lock Device."""
|
2022-01-13 09:34:43 +00:00
|
|
|
super().__init__(coordinator, data)
|
2022-01-11 19:20:15 +00:00
|
|
|
self._attr_code_format = f"^\\d{code_format}$"
|
|
|
|
|
|
|
|
async def async_unlock(self, **kwargs) -> None:
|
|
|
|
"""Send unlock command."""
|
|
|
|
if TYPE_CHECKING:
|
2022-01-13 09:34:43 +00:00
|
|
|
assert self.coordinator.yale, "Connection to API is missing"
|
2022-01-11 19:20:15 +00:00
|
|
|
|
2022-01-13 09:34:43 +00:00
|
|
|
code = kwargs.get(ATTR_CODE, self.coordinator.entry.options.get(CONF_CODE))
|
2022-01-11 19:20:15 +00:00
|
|
|
|
|
|
|
if not code:
|
|
|
|
raise HomeAssistantError(
|
|
|
|
f"No code provided, {self._attr_name} not unlocked"
|
|
|
|
)
|
|
|
|
|
|
|
|
try:
|
|
|
|
get_lock = await self.hass.async_add_executor_job(
|
2022-01-13 09:34:43 +00:00
|
|
|
self.coordinator.yale.lock_api.get, self._attr_name
|
2022-01-11 19:20:15 +00:00
|
|
|
)
|
|
|
|
lock_state = await self.hass.async_add_executor_job(
|
2022-01-13 09:34:43 +00:00
|
|
|
self.coordinator.yale.lock_api.open_lock,
|
2022-01-11 19:20:15 +00:00
|
|
|
get_lock,
|
|
|
|
code,
|
|
|
|
)
|
|
|
|
except (
|
|
|
|
AuthenticationError,
|
|
|
|
ConnectionError,
|
|
|
|
TimeoutError,
|
|
|
|
UnknownError,
|
|
|
|
) as error:
|
|
|
|
raise HomeAssistantError(
|
|
|
|
f"Could not verify unlocking for {self._attr_name}: {error}"
|
|
|
|
) from error
|
|
|
|
|
|
|
|
LOGGER.debug("Door unlock: %s", lock_state)
|
|
|
|
if lock_state:
|
2022-01-13 09:34:43 +00:00
|
|
|
self.coordinator.data["lock_map"][self._attr_unique_id] = "unlocked"
|
2022-01-11 19:20:15 +00:00
|
|
|
self.async_write_ha_state()
|
|
|
|
return
|
|
|
|
raise HomeAssistantError("Could not unlock, check system ready for unlocking")
|
|
|
|
|
|
|
|
async def async_lock(self, **kwargs) -> None:
|
|
|
|
"""Send lock command."""
|
|
|
|
if TYPE_CHECKING:
|
2022-01-13 09:34:43 +00:00
|
|
|
assert self.coordinator.yale, "Connection to API is missing"
|
2022-01-11 19:20:15 +00:00
|
|
|
|
|
|
|
try:
|
|
|
|
get_lock = await self.hass.async_add_executor_job(
|
2022-01-13 09:34:43 +00:00
|
|
|
self.coordinator.yale.lock_api.get, self._attr_name
|
2022-01-11 19:20:15 +00:00
|
|
|
)
|
|
|
|
lock_state = await self.hass.async_add_executor_job(
|
2022-01-13 09:34:43 +00:00
|
|
|
self.coordinator.yale.lock_api.close_lock,
|
2022-01-11 19:20:15 +00:00
|
|
|
get_lock,
|
|
|
|
)
|
|
|
|
except (
|
|
|
|
AuthenticationError,
|
|
|
|
ConnectionError,
|
|
|
|
TimeoutError,
|
|
|
|
UnknownError,
|
|
|
|
) as error:
|
|
|
|
raise HomeAssistantError(
|
|
|
|
f"Could not verify unlocking for {self._attr_name}: {error}"
|
|
|
|
) from error
|
|
|
|
|
|
|
|
LOGGER.debug("Door unlock: %s", lock_state)
|
|
|
|
if lock_state:
|
2022-01-13 09:34:43 +00:00
|
|
|
self.coordinator.data["lock_map"][self._attr_unique_id] = "unlocked"
|
2022-01-11 19:20:15 +00:00
|
|
|
self.async_write_ha_state()
|
|
|
|
return
|
|
|
|
raise HomeAssistantError("Could not unlock, check system ready for unlocking")
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_locked(self) -> bool | None:
|
|
|
|
"""Return true if the lock is locked."""
|
2022-01-13 09:34:43 +00:00
|
|
|
return self.coordinator.data["lock_map"][self._attr_unique_id] == "locked"
|