101 lines
3.3 KiB
Python
101 lines
3.3 KiB
Python
import asyncio
|
|
import logging
|
|
import voluptuous as vol
|
|
import homeassistant.loader as loader
|
|
import homeassistant.helpers.config_validation as cv
|
|
|
|
from homeassistant.const import (CONF_NAME, CONF_WHITELIST, CONF_BLACKLIST)
|
|
from homeassistant.components.camera import PLATFORM_SCHEMA
|
|
from homeassistant.components.camera.mjpeg import (CONF_MJPEG_URL, CONF_STILL_IMAGE_URL, MjpegCamera)
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
DEPENDENCIES = ['shinobi']
|
|
DOMAIN = 'shinobi'
|
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|
vol.Optional(CONF_WHITELIST, default=[]): cv.ensure_list,
|
|
vol.Optional(CONF_BLACKLIST, default=[]): cv.ensure_list
|
|
})
|
|
|
|
shinobi = None
|
|
|
|
|
|
@asyncio.coroutine
|
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|
global shinobi
|
|
shinobi = hass.components.shinobi
|
|
|
|
all_monitors = shinobi.get_all_started_monitors()
|
|
|
|
if not all_monitors:
|
|
_LOGGER.warning('No active monitors found')
|
|
return
|
|
|
|
filtered_monitors = []
|
|
|
|
whitelist = config.get(CONF_WHITELIST)
|
|
blacklist = config.get(CONF_BLACKLIST)
|
|
|
|
if len(whitelist) > 0:
|
|
_LOGGER.debug('Applying whitelist: ' + str(whitelist))
|
|
filtered_monitors = [m for m in all_monitors if m['name'] in whitelist]
|
|
elif len(blacklist) > 0:
|
|
_LOGGER.debug('Applying blacklist: ' + str(blacklist))
|
|
filtered_monitors = [m for m in all_monitors if m['name'] not in blacklist]
|
|
else:
|
|
_LOGGER.debug('No white- or blacklist applied')
|
|
filtered_monitors = all_monitors
|
|
|
|
cameras = []
|
|
|
|
_LOGGER.debug('Filtered monitors: {}'.format(str([monitor['name'] for monitor in filtered_monitors])))
|
|
|
|
for monitor in filtered_monitors:
|
|
device_info = {
|
|
CONF_NAME: monitor['name'],
|
|
CONF_MJPEG_URL: shinobi.monitor_stream_url(monitor['mid']),
|
|
CONF_STILL_IMAGE_URL: shinobi.monitor_still_url(monitor['mid'])
|
|
}
|
|
cameras.append(ShinobiCamera(hass, shinobi, device_info, monitor))
|
|
|
|
if not cameras:
|
|
_LOGGER.warning('No active cameras found')
|
|
return
|
|
|
|
async_add_devices(cameras)
|
|
|
|
|
|
class ShinobiCamera(MjpegCamera):
|
|
"""Representation of a Shinobi Monitor Stream."""
|
|
|
|
def __init__(self, hass, shinobi, device_info, monitor):
|
|
"""Initialize as a subclass of MjpegCamera."""
|
|
super().__init__(device_info)
|
|
self.shinobi = shinobi
|
|
self._monitor_id = monitor['mid']
|
|
self._is_recording = None
|
|
|
|
@property
|
|
def should_poll(self):
|
|
"""Update the recording state periodically."""
|
|
return True
|
|
|
|
def update(self):
|
|
"""Update our recording state from the Shinobi API."""
|
|
_LOGGER.debug('Updating camera state for monitor {}'.format(self._monitor_id))
|
|
|
|
status_response = self.shinobi.get_monitor_state(self._monitor_id)
|
|
|
|
if not status_response:
|
|
_LOGGER.warning('Could not get status for monitor {}'.format(self._monitor_id))
|
|
return
|
|
_LOGGER.debug('Monitor {} is in status {}'.format(self._monitor_id, status_response['mode']))
|
|
self._is_recording = status_response.get('status') == self.shinobi.SHINOBI_CAM_STATE['RECORDING']
|
|
|
|
@property
|
|
def is_recording(self):
|
|
"""Return whether the monitor is in recording mode."""
|
|
return self._is_recording
|
|
|