core/homeassistant/components/template/lock.py

151 lines
4.3 KiB
Python
Raw Normal View History

"""Support for locks which integrates with other components."""
import voluptuous as vol
from homeassistant.components.lock import PLATFORM_SCHEMA, LockEntity
from homeassistant.const import (
2019-07-31 19:25:30 +00:00
CONF_NAME,
CONF_OPTIMISTIC,
CONF_UNIQUE_ID,
2019-07-31 19:25:30 +00:00
CONF_VALUE_TEMPLATE,
STATE_LOCKED,
STATE_ON,
2019-07-31 19:25:30 +00:00
)
from homeassistant.core import callback
from homeassistant.exceptions import TemplateError
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.reload import async_setup_reload_service
from homeassistant.helpers.script import Script
from .const import CONF_AVAILABILITY_TEMPLATE, DOMAIN, PLATFORMS
from .template_entity import TemplateEntity
2019-07-31 19:25:30 +00:00
CONF_LOCK = "lock"
CONF_UNLOCK = "unlock"
2019-07-31 19:25:30 +00:00
DEFAULT_NAME = "Template Lock"
DEFAULT_OPTIMISTIC = False
2019-07-31 19:25:30 +00:00
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Required(CONF_LOCK): cv.SCRIPT_SCHEMA,
vol.Required(CONF_UNLOCK): cv.SCRIPT_SCHEMA,
vol.Required(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_AVAILABILITY_TEMPLATE): cv.template,
2019-07-31 19:25:30 +00:00
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
vol.Optional(CONF_UNIQUE_ID): cv.string,
2019-07-31 19:25:30 +00:00
}
)
async def _async_create_entities(hass, config):
"""Create the Template lock."""
Refactor template components to extract common routines (#27064) * Added availability_template to Template Cover platform * Added availability_template to Template Binary Sensor platform * Added availability_template to Template Fan platform * Added availability_template to Template Light platform * Added availability_template to Template Sensor platform * Added availability_template to Template Switch platform * Added availability_template to Template Vacuum platform * Added availability_template to Template Lock platform * Added to test for invalid values in availability_template * Black and Lint fix * black formatting * Added to test for invalid values in availability_template * black * Added to test for invalid values in availability_template * Added to test for invalid values in availability_template * simplified exception handler * Fixed Entity discovery big and coverage * Added to test for invalid values in availability_template * flake8 * fixed component ID in test * Added to test for invalid values in availability_template * Added to test for invalid values in availability_template * Made availability_template redering erorr more concise * Cleaned template setup * I'll remember to run black every time one of these days... * Refactored Template initialisation * Refactored Template initialisation * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fixed linting issues * Moved availability_template rendering to common loop * Moved availability_template rendering to common loop * Moved availability_template rendering to common loop * Moved availability_template rendering to common loop * Removed 'Magic' string * Removed 'Magic' string and removed duplicate code * Removed 'Magic' string * Removed 'Magic' string * Brought contant into line * Refactored availability_tempalte rendering to common loop * Removed 'Magic' string * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * Fixed tests (magic values and state checks) * Fixed tests (magic values and state checks) * Fixed tests (async, magic values and state checks) * Fixed tests (async, magic values and state checks) * Fixed tests (async, magic values and state checks) * Fixed tests (async, magic values and state checks) * Fixed tests (async, magic values and state checks) * Removed duplicate * Clean up and remove debug * Reverted Dev Container Change
2019-11-26 00:30:49 +00:00
device = config.get(CONF_NAME)
value_template = config.get(CONF_VALUE_TEMPLATE)
Refactor template components to extract common routines (#27064) * Added availability_template to Template Cover platform * Added availability_template to Template Binary Sensor platform * Added availability_template to Template Fan platform * Added availability_template to Template Light platform * Added availability_template to Template Sensor platform * Added availability_template to Template Switch platform * Added availability_template to Template Vacuum platform * Added availability_template to Template Lock platform * Added to test for invalid values in availability_template * Black and Lint fix * black formatting * Added to test for invalid values in availability_template * black * Added to test for invalid values in availability_template * Added to test for invalid values in availability_template * simplified exception handler * Fixed Entity discovery big and coverage * Added to test for invalid values in availability_template * flake8 * fixed component ID in test * Added to test for invalid values in availability_template * Added to test for invalid values in availability_template * Made availability_template redering erorr more concise * Cleaned template setup * I'll remember to run black every time one of these days... * Refactored Template initialisation * Refactored Template initialisation * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Updated AVAILABILITY_TEMPLATE Rendering error * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Moved const to package Const.py * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fix import order (pylint) * Fixed linting issues * Moved availability_template rendering to common loop * Moved availability_template rendering to common loop * Moved availability_template rendering to common loop * Moved availability_template rendering to common loop * Removed 'Magic' string * Removed 'Magic' string and removed duplicate code * Removed 'Magic' string * Removed 'Magic' string * Brought contant into line * Refactored availability_tempalte rendering to common loop * Removed 'Magic' string * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * Cleaned up const and compare lowercase result to 'true' * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * reverted _available back to boolean * Fixed tests (magic values and state checks) * Fixed tests (magic values and state checks) * Fixed tests (async, magic values and state checks) * Fixed tests (async, magic values and state checks) * Fixed tests (async, magic values and state checks) * Fixed tests (async, magic values and state checks) * Fixed tests (async, magic values and state checks) * Removed duplicate * Clean up and remove debug * Reverted Dev Container Change
2019-11-26 00:30:49 +00:00
availability_template = config.get(CONF_AVAILABILITY_TEMPLATE)
2019-07-31 19:25:30 +00:00
return [
TemplateLock(
hass,
device,
value_template,
availability_template,
config.get(CONF_LOCK),
config.get(CONF_UNLOCK),
config.get(CONF_OPTIMISTIC),
config.get(CONF_UNIQUE_ID),
)
]
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up the template lock."""
await async_setup_reload_service(hass, DOMAIN, PLATFORMS)
async_add_entities(await _async_create_entities(hass, config))
class TemplateLock(TemplateEntity, LockEntity):
"""Representation of a template lock."""
2019-07-31 19:25:30 +00:00
def __init__(
self,
hass,
name,
value_template,
availability_template,
2019-07-31 19:25:30 +00:00
command_lock,
command_unlock,
optimistic,
unique_id,
2019-07-31 19:25:30 +00:00
):
"""Initialize the lock."""
super().__init__(availability_template=availability_template)
self._state = None
self._name = name
self._state_template = value_template
domain = __name__.split(".")[-2]
self._command_lock = Script(hass, command_lock, name, domain)
self._command_unlock = Script(hass, command_unlock, name, domain)
self._optimistic = optimistic
self._unique_id = unique_id
@property
def assumed_state(self):
"""Return true if we do optimistic updates."""
return self._optimistic
@property
def name(self):
"""Return the name of the lock."""
return self._name
@property
def unique_id(self):
"""Return the unique id of this lock."""
return self._unique_id
@property
def is_locked(self):
"""Return true if lock is locked."""
return self._state
@callback
def _update_state(self, result):
super()._update_state(result)
if isinstance(result, TemplateError):
self._state = None
return
if isinstance(result, bool):
self._state = result
return
if isinstance(result, str):
self._state = result.lower() in ("true", STATE_ON, STATE_LOCKED)
return
self._state = False
async def async_added_to_hass(self):
"""Register callbacks."""
self.add_template_attribute(
"_state", self._state_template, None, self._update_state
)
await super().async_added_to_hass()
async def async_lock(self, **kwargs):
"""Lock the device."""
if self._optimistic:
self._state = True
self.async_write_ha_state()
await self._command_lock.async_run(context=self._context)
async def async_unlock(self, **kwargs):
"""Unlock the device."""
if self._optimistic:
self._state = False
self.async_write_ha_state()
await self._command_unlock.async_run(context=self._context)