100 lines
3.3 KiB
Python
100 lines
3.3 KiB
Python
"""Support for viewing the camera feed from a DoorBird video doorbell."""
|
|
import asyncio
|
|
import datetime
|
|
import logging
|
|
|
|
import aiohttp
|
|
import async_timeout
|
|
|
|
from homeassistant.components.camera import Camera, SUPPORT_STREAM
|
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|
import homeassistant.util.dt as dt_util
|
|
|
|
from . import DOMAIN as DOORBIRD_DOMAIN
|
|
|
|
_CAMERA_LAST_VISITOR = "{} Last Ring"
|
|
_CAMERA_LAST_MOTION = "{} Last Motion"
|
|
_CAMERA_LIVE = "{} Live"
|
|
_LAST_VISITOR_INTERVAL = datetime.timedelta(minutes=1)
|
|
_LAST_MOTION_INTERVAL = datetime.timedelta(minutes=1)
|
|
_LIVE_INTERVAL = datetime.timedelta(seconds=1)
|
|
_LOGGER = logging.getLogger(__name__)
|
|
_TIMEOUT = 10 # seconds
|
|
|
|
|
|
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
|
"""Set up the DoorBird camera platform."""
|
|
for doorstation in hass.data[DOORBIRD_DOMAIN]:
|
|
device = doorstation.device
|
|
async_add_entities(
|
|
[
|
|
DoorBirdCamera(
|
|
device.live_image_url,
|
|
_CAMERA_LIVE.format(doorstation.name),
|
|
_LIVE_INTERVAL,
|
|
device.rtsp_live_video_url,
|
|
),
|
|
DoorBirdCamera(
|
|
device.history_image_url(1, "doorbell"),
|
|
_CAMERA_LAST_VISITOR.format(doorstation.name),
|
|
_LAST_VISITOR_INTERVAL,
|
|
),
|
|
DoorBirdCamera(
|
|
device.history_image_url(1, "motionsensor"),
|
|
_CAMERA_LAST_MOTION.format(doorstation.name),
|
|
_LAST_MOTION_INTERVAL,
|
|
),
|
|
]
|
|
)
|
|
|
|
|
|
class DoorBirdCamera(Camera):
|
|
"""The camera on a DoorBird device."""
|
|
|
|
def __init__(self, url, name, interval=None, stream_url=None):
|
|
"""Initialize the camera on a DoorBird device."""
|
|
self._url = url
|
|
self._stream_url = stream_url
|
|
self._name = name
|
|
self._last_image = None
|
|
self._supported_features = SUPPORT_STREAM if self._stream_url else 0
|
|
self._interval = interval or datetime.timedelta
|
|
self._last_update = datetime.datetime.min
|
|
super().__init__()
|
|
|
|
async def stream_source(self):
|
|
"""Return the stream source."""
|
|
return self._stream_url
|
|
|
|
@property
|
|
def supported_features(self):
|
|
"""Return supported features."""
|
|
return self._supported_features
|
|
|
|
@property
|
|
def name(self):
|
|
"""Get the name of the camera."""
|
|
return self._name
|
|
|
|
async def async_camera_image(self):
|
|
"""Pull a still image from the camera."""
|
|
now = dt_util.utcnow()
|
|
|
|
if self._last_image and now - self._last_update < self._interval:
|
|
return self._last_image
|
|
|
|
try:
|
|
websession = async_get_clientsession(self.hass)
|
|
with async_timeout.timeout(_TIMEOUT):
|
|
response = await websession.get(self._url)
|
|
|
|
self._last_image = await response.read()
|
|
self._last_update = now
|
|
return self._last_image
|
|
except asyncio.TimeoutError:
|
|
_LOGGER.error("Camera image timed out")
|
|
return self._last_image
|
|
except aiohttp.ClientError as error:
|
|
_LOGGER.error("Error getting camera image: %s", error)
|
|
return self._last_image
|