core/homeassistant/components/surepetcare/__init__.py

141 lines
4.3 KiB
Python

"""The surepetcare integration."""
from __future__ import annotations
from datetime import timedelta
import logging
from surepy import Surepy, SurepyEntity
from surepy.enums import LockState
from surepy.exceptions import SurePetcareAuthenticationError, SurePetcareError
import voluptuous as vol
from homeassistant.const import CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_USERNAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import (
ATTR_FLAP_ID,
ATTR_LOCK_STATE,
CONF_FEEDERS,
CONF_FLAPS,
CONF_PETS,
DOMAIN,
SERVICE_SET_LOCK_STATE,
SURE_API_TIMEOUT,
)
_LOGGER = logging.getLogger(__name__)
PLATFORMS = ["binary_sensor", "sensor"]
SCAN_INTERVAL = timedelta(minutes=3)
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
vol.All(
{
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_FEEDERS): vol.All(
cv.ensure_list, [cv.positive_int]
),
vol.Optional(CONF_FLAPS): vol.All(
cv.ensure_list, [cv.positive_int]
),
vol.Optional(CONF_PETS): vol.All(cv.ensure_list, [cv.positive_int]),
vol.Optional(CONF_SCAN_INTERVAL): cv.time_period,
},
cv.deprecated(CONF_FEEDERS),
cv.deprecated(CONF_FLAPS),
cv.deprecated(CONF_PETS),
cv.deprecated(CONF_SCAN_INTERVAL),
)
)
},
extra=vol.ALLOW_EXTRA,
)
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Sure Petcare integration."""
conf = config[DOMAIN]
hass.data.setdefault(DOMAIN, {})
try:
surepy = Surepy(
conf[CONF_USERNAME],
conf[CONF_PASSWORD],
auth_token=None,
api_timeout=SURE_API_TIMEOUT,
session=async_get_clientsession(hass),
)
except SurePetcareAuthenticationError:
_LOGGER.error("Unable to connect to surepetcare.io: Wrong credentials!")
return False
except SurePetcareError as error:
_LOGGER.error("Unable to connect to surepetcare.io: Wrong %s!", error)
return False
async def _update_method() -> dict[int, SurepyEntity]:
"""Get the latest data from Sure Petcare."""
try:
return await surepy.get_entities(refresh=True)
except SurePetcareError as err:
raise UpdateFailed(f"Unable to fetch data: {err}") from err
coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
name=DOMAIN,
update_method=_update_method,
update_interval=SCAN_INTERVAL,
)
hass.data[DOMAIN] = coordinator
await coordinator.async_refresh()
# load platforms
for platform in PLATFORMS:
hass.async_create_task(
hass.helpers.discovery.async_load_platform(platform, DOMAIN, {}, config)
)
lock_states = {
LockState.UNLOCKED.name.lower(): surepy.sac.unlock,
LockState.LOCKED_IN.name.lower(): surepy.sac.lock_in,
LockState.LOCKED_OUT.name.lower(): surepy.sac.lock_out,
LockState.LOCKED_ALL.name.lower(): surepy.sac.lock,
}
async def handle_set_lock_state(call):
"""Call when setting the lock state."""
flap_id = call.data[ATTR_FLAP_ID]
state = call.data[ATTR_LOCK_STATE]
await lock_states[state](flap_id)
await coordinator.async_request_refresh()
lock_state_service_schema = vol.Schema(
{
vol.Required(ATTR_FLAP_ID): vol.All(
cv.positive_int, vol.In(coordinator.data.keys())
),
vol.Required(ATTR_LOCK_STATE): vol.All(
cv.string,
vol.Lower,
vol.In(lock_states.keys()),
),
}
)
hass.services.async_register(
DOMAIN,
SERVICE_SET_LOCK_STATE,
handle_set_lock_state,
schema=lock_state_service_schema,
)
return True