Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doorbird auth and event data #16504

Closed
wants to merge 8 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
69 changes: 63 additions & 6 deletions homeassistant/components/doorbird.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/doorbird/
"""
import logging

import datetime
oblogic7 marked this conversation as resolved.
Show resolved Hide resolved
import logging
import voluptuous as vol

from homeassistant.components.http import HomeAssistantView
Expand All @@ -24,6 +25,7 @@

CONF_DOORBELL_EVENTS = 'doorbell_events'
CONF_CUSTOM_URL = 'hass_url_override'
CONF_TOKEN = 'token'

DOORBELL_EVENT = 'doorbell'
MOTION_EVENT = 'motionsensor'
Expand All @@ -46,6 +48,7 @@

CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_TOKEN): cv.string,
vol.Required(CONF_DEVICES): vol.All(cv.ensure_list, [DEVICE_SCHEMA])
}),
}, extra=vol.ALLOW_EXTRA)
Expand All @@ -55,8 +58,10 @@ def setup(hass, config):
"""Set up the DoorBird component."""
from doorbirdpy import DoorBird

token = config[DOMAIN].get(CONF_TOKEN)

# Provide an endpoint for the doorstations to call to trigger events
hass.http.register_view(DoorbirdRequestView())
hass.http.register_view(DoorbirdRequestView(token))

doorstations = []

Expand All @@ -75,7 +80,8 @@ def setup(hass, config):
if status[0]:
_LOGGER.info("Connected to DoorBird at %s as %s", device_ip,
username)
doorstation = ConfiguredDoorbird(device, name, events, custom_url)
doorstation = ConfiguredDoorbird(device, name, events, custom_url,
token)
doorstations.append(doorstation)
elif status[1] == 401:
_LOGGER.error("Authorization rejected by DoorBird at %s",
Expand All @@ -99,6 +105,18 @@ def setup(hass, config):
return True


def get_doorstation_by_slug(hass, slug):
oblogic7 marked this conversation as resolved.
Show resolved Hide resolved
"""Get doorstation by slug"""
for doorstation in hass.data[DOMAIN]:
if slugify(doorstation.name) in slug:
return doorstation


def handle_event(event):
oblogic7 marked this conversation as resolved.
Show resolved Hide resolved
"""Dummy handler used to register events in GUI"""
return None


def subscribe_events(hass, doorstation):
"""Initialize the subscriber."""
for sensor_type in doorstation.monitored_events:
Expand All @@ -115,7 +133,8 @@ def subscribe_events(hass, doorstation):

slug = slugify(name)

url = '{}{}/{}'.format(hass_url, API_URL, slug)
url = '{}{}/{}?token={}'.format(hass_url, API_URL, slug,
doorstation.token)

_LOGGER.info("DoorBird will connect to this instance via %s",
url)
Expand All @@ -125,16 +144,20 @@ def subscribe_events(hass, doorstation):

doorstation.device.subscribe_notification(event_type, url)

# Register a dummy listener so event is listed in GUI
hass.bus.listen('{}_{}'.format(DOMAIN, slug), handle_event)


class ConfiguredDoorbird():
"""Attach additional information to pass along with configured device."""

def __init__(self, device, name, events=None, custom_url=None):
def __init__(self, device, name, events=None, custom_url=None, token=None):
"""Initialize configured device."""
self._name = name
self._device = device
self._custom_url = custom_url
self._monitored_events = events
self._token = token

@property
def name(self):
Expand All @@ -159,6 +182,21 @@ def monitored_events(self):

return self._monitored_events

@property
def token(self):
"""Get token used to authenticate event endpoint"""
return self._token

def get_event_data(self):
"""Get data to pass along with HA event."""
return {
'timestamp': datetime.datetime.now(),
oblogic7 marked this conversation as resolved.
Show resolved Hide resolved
'live_video_url': self._device.live_video_url,
'live_image_url': self._device.live_image_url,
'rtsp_live_video_url': self._device.rtsp_live_video_url,
'html5_viewer_url': self._device.html5_viewer_url
}


class DoorbirdRequestView(HomeAssistantView):
"""Provide a page for the device to call."""
Expand All @@ -168,11 +206,30 @@ class DoorbirdRequestView(HomeAssistantView):
name = API_URL[1:].replace('/', ':')
extra_urls = [API_URL + '/{sensor}']

def __init__(self, token):
HomeAssistantView.__init__(self)
self._token = token

# pylint: disable=no-self-use
async def get(self, request, sensor):
"""Respond to requests from the device."""

request_token = request.query.get('token')

authenticated = request_token == self._token

if request_token == '' or not authenticated:
return self.json_message('Unauthorized.')

hass = request.app['hass']

hass.bus.async_fire('{}_{}'.format(DOMAIN, sensor))
doorstation = get_doorstation_by_slug(hass, sensor)

if doorstation is not None:
event_data = doorstation.get_event_data()
else:
event_data = {}

hass.bus.async_fire('{}_{}'.format(DOMAIN, sensor), event_data)

return 'OK'