core/homeassistant/components/surepetcare/__init__.py

164 lines
4.4 KiB
Python

"""Support for Sure Petcare cat/pet flaps."""
import logging
from surepy import (
SurePetcare,
SurePetcareAuthenticationError,
SurePetcareError,
SureThingID,
)
import voluptuous as vol
from homeassistant.const import (
CONF_ID,
CONF_NAME,
CONF_PASSWORD,
CONF_SCAN_INTERVAL,
CONF_TYPE,
CONF_USERNAME,
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.event import async_track_time_interval
from .const import (
CONF_FLAPS,
CONF_HOUSEHOLD_ID,
CONF_PETS,
DATA_SURE_PETCARE,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
SPC,
TOPIC_UPDATE,
)
_LOGGER = logging.getLogger(__name__)
FLAP_SCHEMA = vol.Schema(
{vol.Required(CONF_ID): cv.positive_int, vol.Required(CONF_NAME): cv.string}
)
PET_SCHEMA = vol.Schema(
{vol.Required(CONF_ID): cv.positive_int, vol.Required(CONF_NAME): cv.string}
)
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_HOUSEHOLD_ID): cv.positive_int,
vol.Required(CONF_FLAPS): vol.All(cv.ensure_list, [FLAP_SCHEMA]),
vol.Required(CONF_PETS): vol.All(cv.ensure_list, [PET_SCHEMA]),
vol.Optional(
CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL
): cv.time_period,
}
)
},
extra=vol.ALLOW_EXTRA,
)
async def async_setup(hass, config):
"""Initialize the Sure Petcare component."""
conf = config[DOMAIN]
# update interval
scan_interval = conf[CONF_SCAN_INTERVAL]
# shared data
hass.data[DOMAIN] = hass.data[DATA_SURE_PETCARE] = {}
# sure petcare api connection
try:
surepy = SurePetcare(
conf[CONF_USERNAME],
conf[CONF_PASSWORD],
conf[CONF_HOUSEHOLD_ID],
hass.loop,
async_get_clientsession(hass),
)
await surepy.refresh_token()
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
# add flaps
things = [
{
CONF_NAME: flap[CONF_NAME],
CONF_ID: flap[CONF_ID],
CONF_TYPE: SureThingID.FLAP.name,
}
for flap in conf[CONF_FLAPS]
]
# add pets
things.extend(
[
{
CONF_NAME: pet[CONF_NAME],
CONF_ID: pet[CONF_ID],
CONF_TYPE: SureThingID.PET.name,
}
for pet in conf[CONF_PETS]
]
)
spc = hass.data[DATA_SURE_PETCARE][SPC] = SurePetcareAPI(
hass, surepy, things, conf[CONF_HOUSEHOLD_ID]
)
# initial update
await spc.async_update()
async_track_time_interval(hass, spc.async_update, scan_interval)
# load platforms
hass.async_create_task(
hass.helpers.discovery.async_load_platform("binary_sensor", DOMAIN, {}, config)
)
hass.async_create_task(
hass.helpers.discovery.async_load_platform("sensor", DOMAIN, {}, config)
)
return True
class SurePetcareAPI:
"""Define a generic Sure Petcare object."""
def __init__(self, hass, surepy, ids, household_id):
"""Initialize the Sure Petcare object."""
self.hass = hass
self.surepy = surepy
self.household_id = household_id
self.ids = ids
self.states = {}
async def async_update(self, args=None):
"""Refresh Sure Petcare data."""
for thing in self.ids:
sure_id = thing[CONF_ID]
sure_type = thing[CONF_TYPE]
try:
type_state = self.states.setdefault(sure_type, {})
if sure_type == SureThingID.FLAP.name:
type_state[sure_id] = await self.surepy.get_flap_data(sure_id)
elif sure_type == SureThingID.PET.name:
type_state[sure_id] = await self.surepy.get_pet_data(sure_id)
except SurePetcareError as error:
_LOGGER.error("Unable to retrieve data from surepetcare.io: %s", error)
async_dispatcher_send(self.hass, TOPIC_UPDATE)