From 4d620be9db1038316d9bb76be4ba2a05ef1a7ca8 Mon Sep 17 00:00:00 2001 From: Ben Lebherz Date: Thu, 9 Sep 2021 23:48:28 +0200 Subject: [PATCH] add service to set pet location, see #5 --- __init__.py | 76 ++++++++++++++++++++++++++++++++++++++++++++------- const.py | 6 +++- services.yaml | 17 ++++++++++++ 3 files changed, 88 insertions(+), 11 deletions(-) diff --git a/__init__.py b/__init__.py index c679e2a..6971a42 100644 --- a/__init__.py +++ b/__init__.py @@ -16,7 +16,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from surepy import Surepy from surepy.entities import SurepyEntity -from surepy.enums import EntityType, LockState +from surepy.enums import EntityType, Location, LockState from surepy.exceptions import SurePetcareAuthenticationError, SurePetcareError import voluptuous as vol @@ -24,7 +24,10 @@ from .const import ( ATTR_FLAP_ID, ATTR_LOCK_STATE, + ATTR_PET_ID, + ATTR_WHERE, DOMAIN, + SERVICE_PET_LOCATION, SERVICE_SET_LOCK_STATE, SPC, SURE_API_TIMEOUT, @@ -130,19 +133,25 @@ def __init__( self.states: dict[int, Any] = {} + async def set_pet_location(self, pet_id: int, location: Location) -> None: + """Update the lock state of a flap.""" + + await self.surepy.sac.set_pet_location(pet_id, location) + async def set_lock_state(self, flap_id: int, state: str) -> None: """Update the lock state of a flap.""" # https://github.com/PyCQA/pylint/issues/2062 # pylint: disable=no-member - if state == LockState.UNLOCKED.name.lower(): - await self.surepy.sac.unlock(flap_id) - elif state == LockState.LOCKED_IN.name.lower(): - await self.surepy.sac.lock_in(flap_id) - elif state == LockState.LOCKED_OUT.name.lower(): - await self.surepy.sac.lock_out(flap_id) - elif state == LockState.LOCKED_ALL.name.lower(): - await self.surepy.sac.lock(flap_id) + lock_states = { + LockState.UNLOCKED.name.lower(): self.surepy.sac.unlock, + LockState.LOCKED_IN.name.lower(): self.surepy.sac.lock_in, + LockState.LOCKED_OUT.name.lower(): self.surepy.sac.lock_out, + LockState.LOCKED_ALL.name.lower(): self.surepy.sac.lock, + } + + # elegant functions dict to choose the right function | idea by @janiversen + await lock_states[state.lower()](flap_id) async def async_setup(self) -> bool: """Set up the Sure Petcare integration.""" @@ -174,6 +183,54 @@ async def async_setup(self) -> bool: # ) # ) + surepy_entities: list[SurepyEntity] = self.coordinator.data.values() + + pet_ids = [ + entity.id for entity in surepy_entities if entity.type == EntityType.PET + ] + + pet_location_service_schema = vol.Schema( + { + vol.Required(ATTR_PET_ID): vol.Any(cv.positive_int, vol.In(pet_ids)), + vol.Required(ATTR_WHERE): vol.Any( + cv.string, + vol.In( + [ + # https://github.com/PyCQA/pylint/issues/2062 + # pylint: disable=no-member + Location.INSIDE.name.title(), + Location.OUTSIDE.name.title(), + # Location.UNKNOWN.name.title(), + ] + ), + ), + } + ) + + async def handle_set_pet_location(call: Any) -> None: + """Call when setting the lock state.""" + + try: + + if (pet_id := int(call.data.get(ATTR_PET_ID))) and ( + where := str(call.data.get(ATTR_WHERE)) + ): + + await self.set_pet_location(pet_id, Location[where.upper()]) + await self.coordinator.async_request_refresh() + + except ValueError as error: + _LOGGER.error( + "🐾 \x1b[38;2;255;26;102m·\x1b[0m arguments of wrong type: %s", error + ) + + self.hass.services.async_register( + DOMAIN, + SERVICE_PET_LOCATION, + handle_set_pet_location, + schema=pet_location_service_schema, + ) + async def handle_set_lock_state(call: Any) -> None: """Call when setting the lock state.""" @@ -183,7 +240,6 @@ async def handle_set_lock_state(call: Any) -> None: await self.set_lock_state(flap_id, lock_state) await self.coordinator.async_request_refresh() - surepy_entities: list[SurepyEntity] = self.coordinator.data.values() flap_ids = [ entity.id for entity in surepy_entities diff --git a/const.py b/const.py index ada23fc..0fdaff2 100644 --- a/const.py +++ b/const.py @@ -17,7 +17,11 @@ SURE_BATT_VOLTAGE_LOW = 1.25 SURE_BATT_VOLTAGE_DIFF = SURE_BATT_VOLTAGE_FULL - SURE_BATT_VOLTAGE_LOW -# lock state service +# services SERVICE_SET_LOCK_STATE = "set_lock_state" ATTR_FLAP_ID = "flap_id" ATTR_LOCK_STATE = "lock_state" + +SERVICE_PET_LOCATION = "set_pet_location" +ATTR_PET_ID = "pet_id" +ATTR_WHERE = "where" diff --git a/services.yaml b/services.yaml index c93cdfc..7cded7f 100644 --- a/services.yaml +++ b/services.yaml @@ -16,3 +16,20 @@ set_lock_state: selector: select: { options: ["locked_all", "locked_in", "locked_out", "unlocked"] } +set_pet_location: + name: Set Pet location + description: Sets the location of a pet + fields: + pet_id: + name: Pet ID + description: Pet ID to set the location for + required: true + example: 31337 + selector: + text: + where: + name: Location + description: Current location of the pet + required: true + example: "Inside" + selector: { select: { options: ["Inside", "Outside"] } }