core/homeassistant/components/doorbird.py

181 lines
5.3 KiB
Python

"""
Support for DoorBird device.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/doorbird/
"""
import logging
import asyncio
import voluptuous as vol
from homeassistant.components.http import HomeAssistantView
from homeassistant.const import CONF_HOST, CONF_USERNAME, \
CONF_PASSWORD, CONF_NAME, CONF_DEVICES, CONF_MONITORED_CONDITIONS
import homeassistant.helpers.config_validation as cv
from homeassistant.util import slugify
REQUIREMENTS = ['DoorBirdPy==0.1.3']
_LOGGER = logging.getLogger(__name__)
DOMAIN = 'doorbird'
API_URL = '/api/{}'.format(DOMAIN)
CONF_DOORBELL_EVENTS = 'doorbell_events'
CONF_CUSTOM_URL = 'hass_url_override'
DOORBELL_EVENT = 'doorbell'
MOTION_EVENT = 'motionsensor'
# Sensor types: Name, device_class, event
SENSOR_TYPES = {
'doorbell': ['Button', 'occupancy', DOORBELL_EVENT],
'motion': ['Motion', 'motion', MOTION_EVENT],
}
DEVICE_SCHEMA = vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_CUSTOM_URL): cv.string,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_MONITORED_CONDITIONS, default=[]):
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
})
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_DEVICES): vol.All(cv.ensure_list, [DEVICE_SCHEMA])
}),
}, extra=vol.ALLOW_EXTRA)
def setup(hass, config):
"""Set up the DoorBird component."""
from doorbirdpy import DoorBird
# Provide an endpoint for the doorstations to call to trigger events
hass.http.register_view(DoorbirdRequestView())
doorstations = []
for index, doorstation_config in enumerate(config[DOMAIN][CONF_DEVICES]):
device_ip = doorstation_config.get(CONF_HOST)
username = doorstation_config.get(CONF_USERNAME)
password = doorstation_config.get(CONF_PASSWORD)
custom_url = doorstation_config.get(CONF_CUSTOM_URL)
events = doorstation_config.get(CONF_MONITORED_CONDITIONS)
name = (doorstation_config.get(CONF_NAME)
or 'DoorBird {}'.format(index + 1))
device = DoorBird(device_ip, username, password)
status = device.ready()
if status[0]:
_LOGGER.info("Connected to DoorBird at %s as %s", device_ip,
username)
doorstation = ConfiguredDoorbird(device, name, events, custom_url)
doorstations.append(doorstation)
elif status[1] == 401:
_LOGGER.error("Authorization rejected by DoorBird at %s",
device_ip)
return False
else:
_LOGGER.error("Could not connect to DoorBird at %s: Error %s",
device_ip, str(status[1]))
return False
# SETUP EVENT SUBSCRIBERS
if events is not None:
# This will make HA the only service that receives events.
doorstation.device.reset_notifications()
# Subscribe to doorbell or motion events
subscribe_events(hass, doorstation)
hass.data[DOMAIN] = doorstations
return True
def subscribe_events(hass, doorstation):
"""Initialize the subscriber."""
for sensor_type in doorstation.monitored_events:
name = '{} {}'.format(doorstation.name,
SENSOR_TYPES[sensor_type][0])
event_type = SENSOR_TYPES[sensor_type][2]
# Get the URL of this server
hass_url = hass.config.api.base_url
# Override url if another is specified onth configuration
if doorstation.custom_url is not None:
hass_url = doorstation.custom_url
slug = slugify(name)
url = '{}{}/{}'.format(hass_url, API_URL, slug)
_LOGGER.info("DoorBird will connect to this instance via %s",
url)
_LOGGER.info("You may use the following event name for automations"
": %s_%s", DOMAIN, slug)
doorstation.device.subscribe_notification(event_type, url)
class ConfiguredDoorbird():
"""Attach additional information to pass along with configured device."""
def __init__(self, device, name, events=None, custom_url=None):
"""Initialize configured device."""
self._name = name
self._device = device
self._custom_url = custom_url
self._monitored_events = events
@property
def name(self):
"""Custom device name."""
return self._name
@property
def device(self):
"""The configured device."""
return self._device
@property
def custom_url(self):
"""Custom url for device."""
return self._custom_url
@property
def monitored_events(self):
"""Get monitored events."""
if self._monitored_events is None:
return []
return self._monitored_events
class DoorbirdRequestView(HomeAssistantView):
"""Provide a page for the device to call."""
requires_auth = False
url = API_URL
name = API_URL[1:].replace('/', ':')
extra_urls = [API_URL + '/{sensor}']
# pylint: disable=no-self-use
@asyncio.coroutine
def get(self, request, sensor):
"""Respond to requests from the device."""
hass = request.app['hass']
hass.bus.async_fire('{}_{}'.format(DOMAIN, sensor))
return 'OK'