core/homeassistant/components/canary.py

118 lines
3.7 KiB
Python

"""
Support for Canary.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/canary/
"""
import logging
from datetime import timedelta
import voluptuous as vol
from requests import ConnectTimeout, HTTPError
import homeassistant.helpers.config_validation as cv
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD, CONF_TIMEOUT
from homeassistant.helpers import discovery
from homeassistant.util import Throttle
REQUIREMENTS = ['py-canary==0.2.3']
_LOGGER = logging.getLogger(__name__)
NOTIFICATION_ID = 'canary_notification'
NOTIFICATION_TITLE = 'Canary Setup'
DOMAIN = 'canary'
DATA_CANARY = 'canary'
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
DEFAULT_TIMEOUT = 10
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
}),
}, extra=vol.ALLOW_EXTRA)
CANARY_COMPONENTS = [
'alarm_control_panel', 'camera', 'sensor'
]
def setup(hass, config):
"""Set up the Canary component."""
conf = config[DOMAIN]
username = conf.get(CONF_USERNAME)
password = conf.get(CONF_PASSWORD)
timeout = conf.get(CONF_TIMEOUT)
try:
hass.data[DATA_CANARY] = CanaryData(username, password, timeout)
except (ConnectTimeout, HTTPError) as ex:
_LOGGER.error("Unable to connect to Canary service: %s", str(ex))
hass.components.persistent_notification.create(
'Error: {}<br />'
'You will need to restart hass after fixing.'
''.format(ex),
title=NOTIFICATION_TITLE,
notification_id=NOTIFICATION_ID)
return False
for component in CANARY_COMPONENTS:
discovery.load_platform(hass, component, DOMAIN, {}, config)
return True
class CanaryData(object):
"""Get the latest data and update the states."""
def __init__(self, username, password, timeout):
"""Init the Canary data object."""
from canary.api import Api
self._api = Api(username, password, timeout)
self._locations_by_id = {}
self._readings_by_device_id = {}
self._entries_by_location_id = {}
self.update()
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self, **kwargs):
"""Get the latest data from py-canary."""
for location in self._api.get_locations():
location_id = location.location_id
self._locations_by_id[location_id] = location
self._entries_by_location_id[location_id] = self._api.get_entries(
location_id, entry_type="motion", limit=1)
for device in location.devices:
if device.is_online:
self._readings_by_device_id[device.device_id] = \
self._api.get_latest_readings(device.device_id)
@property
def locations(self):
"""Return a list of locations."""
return self._locations_by_id.values()
def get_motion_entries(self, location_id):
"""Return a list of motion entries based on location_id."""
return self._entries_by_location_id.get(location_id, [])
def get_location(self, location_id):
"""Return a location based on location_id."""
return self._locations_by_id.get(location_id, [])
def get_readings(self, device_id):
"""Return a list of readings based on device_id."""
return self._readings_by_device_id.get(device_id, [])
def set_location_mode(self, location_id, mode_name, is_private=False):
"""Set location mode."""
self._api.set_location_mode(location_id, mode_name, is_private)
self.update(no_throttle=True)