From 7c23de469ebd4cd7b81d5a8a2db5ac8412135ffb Mon Sep 17 00:00:00 2001 From: shbatm Date: Sun, 26 Feb 2023 01:12:00 -0600 Subject: [PATCH] Add ISY994 services to set and delete lock codes (#88754) --- homeassistant/components/isy994/lock.py | 56 ++++++++++++++++--- homeassistant/components/isy994/manifest.json | 2 +- homeassistant/components/isy994/services.py | 13 +++++ homeassistant/components/isy994/services.yaml | 46 +++++++++++++++ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 6 files changed, 111 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/isy994/lock.py b/homeassistant/components/isy994/lock.py index c5372135bbb..9bf487def07 100644 --- a/homeassistant/components/isy994/lock.py +++ b/homeassistant/components/isy994/lock.py @@ -8,16 +8,43 @@ from pyisy.constants import ISY_VALUE_UNKNOWN from homeassistant.components.lock import LockEntity from homeassistant.config_entries import ConfigEntry from homeassistant.const import Platform -from homeassistant.core import HomeAssistant +from homeassistant.core import HomeAssistant, callback +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity import DeviceInfo -from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.entity_platform import ( + AddEntitiesCallback, + async_get_current_platform, +) -from .const import _LOGGER, DOMAIN +from .const import DOMAIN from .entity import ISYNodeEntity, ISYProgramEntity +from .services import ( + SERVICE_DELETE_USER_CODE_SCHEMA, + SERVICE_DELETE_ZWAVE_LOCK_USER_CODE, + SERVICE_SET_USER_CODE_SCHEMA, + SERVICE_SET_ZWAVE_LOCK_USER_CODE, +) VALUE_TO_STATE = {0: False, 100: True} +@callback +def async_setup_lock_services(hass: HomeAssistant) -> None: + """Create lock-specific services for the ISY Integration.""" + platform = async_get_current_platform() + + platform.async_register_entity_service( + SERVICE_SET_ZWAVE_LOCK_USER_CODE, + SERVICE_SET_USER_CODE_SCHEMA, + "async_set_zwave_lock_user_code", + ) + platform.async_register_entity_service( + SERVICE_DELETE_ZWAVE_LOCK_USER_CODE, + SERVICE_DELETE_USER_CODE_SCHEMA, + "async_delete_zwave_lock_user_code", + ) + + async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: @@ -32,6 +59,7 @@ async def async_setup_entry( entities.append(ISYLockProgramEntity(name, status, actions)) async_add_entities(entities) + async_setup_lock_services(hass) class ISYLockEntity(ISYNodeEntity, LockEntity): @@ -47,12 +75,26 @@ class ISYLockEntity(ISYNodeEntity, LockEntity): async def async_lock(self, **kwargs: Any) -> None: """Send the lock command to the ISY device.""" if not await self._node.secure_lock(): - _LOGGER.error("Unable to lock device") + raise HomeAssistantError(f"Unable to lock device {self._node.address}") async def async_unlock(self, **kwargs: Any) -> None: """Send the unlock command to the ISY device.""" if not await self._node.secure_unlock(): - _LOGGER.error("Unable to lock device") + raise HomeAssistantError(f"Unable to unlock device {self._node.address}") + + async def async_set_zwave_lock_user_code(self, user_num: int, code: int) -> None: + """Set a user lock code for a Z-Wave Lock.""" + if not await self._node.set_zwave_lock_code(user_num, code): + raise HomeAssistantError( + f"Could not set user code {user_num} for {self._node.address}" + ) + + async def async_delete_zwave_lock_user_code(self, user_num: int) -> None: + """Delete a user lock code for a Z-Wave Lock.""" + if not await self._node.delete_zwave_lock_code(user_num): + raise HomeAssistantError( + f"Could not delete user code {user_num} for {self._node.address}" + ) class ISYLockProgramEntity(ISYProgramEntity, LockEntity): @@ -66,9 +108,9 @@ class ISYLockProgramEntity(ISYProgramEntity, LockEntity): async def async_lock(self, **kwargs: Any) -> None: """Lock the device.""" if not await self._actions.run_then(): - _LOGGER.error("Unable to lock device") + raise HomeAssistantError(f"Unable to lock device {self._node.address}") async def async_unlock(self, **kwargs: Any) -> None: """Unlock the device.""" if not await self._actions.run_else(): - _LOGGER.error("Unable to unlock device") + raise HomeAssistantError(f"Unable to unlock device {self._node.address}") diff --git a/homeassistant/components/isy994/manifest.json b/homeassistant/components/isy994/manifest.json index 991b79e7be9..3aa81027b4f 100644 --- a/homeassistant/components/isy994/manifest.json +++ b/homeassistant/components/isy994/manifest.json @@ -24,7 +24,7 @@ "integration_type": "hub", "iot_class": "local_push", "loggers": ["pyisy"], - "requirements": ["pyisy==3.1.13"], + "requirements": ["pyisy==3.1.14"], "ssdp": [ { "manufacturer": "Universal Devices Inc.", diff --git a/homeassistant/components/isy994/services.py b/homeassistant/components/isy994/services.py index 05e0425c3f5..ea66bc90130 100644 --- a/homeassistant/components/isy994/services.py +++ b/homeassistant/components/isy994/services.py @@ -52,8 +52,14 @@ SERVICE_RENAME_NODE = "rename_node" SERVICE_SET_ON_LEVEL = "set_on_level" SERVICE_SET_RAMP_RATE = "set_ramp_rate" +# Services valid only for Z-Wave Locks +SERVICE_SET_ZWAVE_LOCK_USER_CODE = "set_zwave_lock_user_code" +SERVICE_DELETE_ZWAVE_LOCK_USER_CODE = "delete_zwave_lock_user_code" + CONF_PARAMETER = "parameter" CONF_PARAMETERS = "parameters" +CONF_USER_NUM = "user_num" +CONF_CODE = "code" CONF_VALUE = "value" CONF_INIT = "init" CONF_ISY = "isy" @@ -129,6 +135,13 @@ SERVICE_SET_ZWAVE_PARAMETER_SCHEMA = { vol.Required(CONF_SIZE): vol.All(vol.Coerce(int), vol.In(VALID_PARAMETER_SIZES)), } +SERVICE_SET_USER_CODE_SCHEMA = { + vol.Required(CONF_USER_NUM): vol.Coerce(int), + vol.Required(CONF_CODE): vol.Coerce(int), +} + +SERVICE_DELETE_USER_CODE_SCHEMA = {vol.Required(CONF_USER_NUM): vol.Coerce(int)} + SERVICE_SET_VARIABLE_SCHEMA = vol.All( cv.has_at_least_one_key(CONF_ADDRESS, CONF_TYPE, CONF_NAME), vol.Schema( diff --git a/homeassistant/components/isy994/services.yaml b/homeassistant/components/isy994/services.yaml index e336eaa574b..89b6c4d33d3 100644 --- a/homeassistant/components/isy994/services.yaml +++ b/homeassistant/components/isy994/services.yaml @@ -118,6 +118,52 @@ set_zwave_parameter: - "1" - "2" - "4" +set_zwave_lock_user_code: + name: Set Z-Wave Lock User Code + description: >- + Set a Z-Wave Lock User Code via the ISY. + target: + entity: + integration: isy994 + domain: lock + fields: + user_num: + name: User Number + description: The user slot number on the lock + required: true + example: 8 + selector: + number: + min: 1 + max: 255 + code: + name: Code + description: The code to set for the user. + required: true + example: 33491663 + selector: + number: + min: 1 + max: 99999999 + mode: box +delete_zwave_lock_user_code: + name: Delete Z-Wave Lock User Code + description: >- + Delete a Z-Wave Lock User Code via the ISY. + target: + entity: + integration: isy994 + domain: lock + fields: + user_num: + name: User Number + description: The user slot number on the lock + required: true + example: 8 + selector: + number: + min: 1 + max: 255 rename_node: name: Rename Node on ISY description: >- diff --git a/requirements_all.txt b/requirements_all.txt index 9fae25122a4..4d903ffaaef 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1708,7 +1708,7 @@ pyirishrail==0.0.2 pyiss==1.0.1 # homeassistant.components.isy994 -pyisy==3.1.13 +pyisy==3.1.14 # homeassistant.components.itach pyitachip2ir==0.0.7 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 22c4b7e4dff..ecda31f4c36 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1227,7 +1227,7 @@ pyiqvia==2022.04.0 pyiss==1.0.1 # homeassistant.components.isy994 -pyisy==3.1.13 +pyisy==3.1.14 # homeassistant.components.kaleidescape pykaleidescape==1.0.1