cleanup
This commit is contained in:
@@ -5,8 +5,8 @@ import homeassistant.loader as loader
|
|||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
from homeassistant.const import (CONF_NAME, CONF_WHITELIST, CONF_BLACKLIST)
|
from homeassistant.const import (CONF_NAME, CONF_WHITELIST, CONF_BLACKLIST)
|
||||||
from homeassistant.components.camera.mjpeg import (
|
from homeassistant.components.camera import PLATFORM_SCHEMA
|
||||||
CONF_MJPEG_URL, CONF_STILL_IMAGE_URL, MjpegCamera)
|
from homeassistant.components.camera.mjpeg import (CONF_MJPEG_URL, CONF_STILL_IMAGE_URL, MjpegCamera)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -15,12 +15,11 @@ DOMAIN = 'shinobi'
|
|||||||
|
|
||||||
shinobi = loader.get_component('shinobi')
|
shinobi = loader.get_component('shinobi')
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
DOMAIN: vol.Schema({
|
vol.Optional(CONF_WHITELIST, default=[]): cv.ensure_list,
|
||||||
vol.Optional(CONF_WHITELIST): cv.ensure_list,
|
vol.Optional(CONF_BLACKLIST, default=[]): cv.ensure_list
|
||||||
vol.Optional(CONF_BLACKLIST): cv.ensure_list
|
|
||||||
})
|
})
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
@@ -32,13 +31,13 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
|
|
||||||
filtered_monitors = []
|
filtered_monitors = []
|
||||||
|
|
||||||
whitelist = config.get(CONF_WHITELIST, [])
|
whitelist = config.get(CONF_WHITELIST)
|
||||||
blacklist = config.get(CONF_BLACKLIST, [])
|
blacklist = config.get(CONF_BLACKLIST)
|
||||||
|
|
||||||
if whitelist and len(whitelist) > 0:
|
if len(whitelist) > 0:
|
||||||
_LOGGER.debug('Applying whitelist: ' + str(whitelist))
|
_LOGGER.debug('Applying whitelist: ' + str(whitelist))
|
||||||
filtered_monitors = [m for m in all_monitors if m['name'] in whitelist]
|
filtered_monitors = [m for m in all_monitors if m['name'] in whitelist]
|
||||||
elif blacklist and len(blacklist) > 0:
|
elif len(blacklist) > 0:
|
||||||
_LOGGER.debug('Applying blacklist: ' + str(blacklist))
|
_LOGGER.debug('Applying blacklist: ' + str(blacklist))
|
||||||
filtered_monitors = [m for m in all_monitors if m['name'] not in blacklist]
|
filtered_monitors = [m for m in all_monitors if m['name'] not in blacklist]
|
||||||
else:
|
else:
|
||||||
@@ -88,7 +87,7 @@ class ShinobiCamera(MjpegCamera):
|
|||||||
_LOGGER.warning('Could not get status for monitor {}'.format(self._monitor_id))
|
_LOGGER.warning('Could not get status for monitor {}'.format(self._monitor_id))
|
||||||
return
|
return
|
||||||
_LOGGER.debug('Monitor {} is in status {}'.format(self._monitor_id, status_response['mode']))
|
_LOGGER.debug('Monitor {} is in status {}'.format(self._monitor_id, status_response['mode']))
|
||||||
self._is_recording = status_response.get('status') == shinobi.SHINOBI_CAM_RECORDING
|
self._is_recording = status_response.get('status') == shinobi.SHINOBI_CAM_STATE['RECORDING']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_recording(self):
|
def is_recording(self):
|
||||||
|
|||||||
@@ -1,30 +1,31 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import json
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (CONF_HOST, CONF_API_KEY, CONF_SSL)
|
||||||
CONF_HOST, CONF_API_KEY, CONF_SSL)
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = 'shinobi'
|
DOMAIN = 'shinobi'
|
||||||
DEFAULT_TIMEOUT = 10
|
|
||||||
DEFAULT_SSL = False
|
DEFAULT_SSL = False
|
||||||
|
DEFAULT_TIMEOUT = 10
|
||||||
|
|
||||||
SHINOBI_CAM_DISABLED = 'stop'
|
SHINOBI = {}
|
||||||
SHINOBI_CAM_WATCHING = 'start'
|
|
||||||
SHINOBI_CAM_RECORDING = 'record'
|
SHINOBI_CAM_STATE = {
|
||||||
|
'DISABLED': 'stop',
|
||||||
|
'RECORDING': 'record',
|
||||||
|
'WATCHING': 'start'
|
||||||
|
}
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: vol.Schema({
|
DOMAIN: vol.Schema({
|
||||||
vol.Required(CONF_HOST): cv.string,
|
vol.Required(CONF_HOST): cv.string,
|
||||||
vol.Required(CONF_API_KEY): cv.string,
|
vol.Required(CONF_API_KEY): cv.string,
|
||||||
vol.Required('group_key'): cv.string,
|
vol.Required('group_key'): cv.string,
|
||||||
vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
|
vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean
|
||||||
vol.Optional('monitors', default=[]): cv.ensure_list
|
|
||||||
})
|
})
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
@@ -33,44 +34,44 @@ CONFIG_SCHEMA = vol.Schema({
|
|||||||
def async_setup(hass, config):
|
def async_setup(hass, config):
|
||||||
|
|
||||||
global SHINOBI
|
global SHINOBI
|
||||||
SHINOBI = {}
|
|
||||||
|
|
||||||
conf = config[DOMAIN]
|
conf = config[DOMAIN]
|
||||||
if conf[CONF_SSL]:
|
|
||||||
|
if conf.get(CONF_SSL):
|
||||||
schema = 'https'
|
schema = 'https'
|
||||||
else:
|
else:
|
||||||
schema = 'http'
|
schema = 'http'
|
||||||
|
|
||||||
server_origin = '{}://{}'.format(schema, conf[CONF_HOST])
|
server_origin = '{}://{}'.format(schema, conf.get(CONF_HOST))
|
||||||
|
|
||||||
SHINOBI['server_origin'] = server_origin
|
SHINOBI['server_origin'] = server_origin
|
||||||
SHINOBI['api_key'] = conf.get(CONF_API_KEY, None)
|
SHINOBI['api_key'] = conf.get(CONF_API_KEY)
|
||||||
SHINOBI['group_key'] = conf.get('group_key', None)
|
SHINOBI['group_key'] = conf.get('group_key')
|
||||||
SHINOBI['monitors'] = conf.get('monitors')
|
|
||||||
|
|
||||||
hass.data[DOMAIN] = SHINOBI
|
# Unfortunately, the api does not return error codes. The only way to
|
||||||
|
# check if the credentials are working is to check the response of an
|
||||||
# unfortunately, the api does not return error codes. The only way to check if the credentials are working is to check the response of an (arbitrary) request (e.g. get all monitors)
|
# (arbitrary) request (e.g. to get all monitors).
|
||||||
try:
|
try:
|
||||||
check_creds_response = get_all_started_monitors()
|
check_creds_response = get_all_started_monitors()
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# expected response contains a list with activated monitors (or an empty list)
|
# Expected response contains a list with activated monitors (or an empty
|
||||||
|
# list if no monitors activated).
|
||||||
if isinstance(check_creds_response, list):
|
if isinstance(check_creds_response, list):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# response payload contains ok: false if authentication has not been successful
|
# Response payload contains {"ok": "false",…} if authentication has not been successful.
|
||||||
if not check_creds_response.ok:
|
if not check_creds_response.ok:
|
||||||
_LOGGER.error('Wrong api_key or non existing group_key provided')
|
_LOGGER.error('Wrong api_key or non existing group_key provided')
|
||||||
else:
|
else:
|
||||||
_LOGGER.error('Unknown error occured while retrieving monitors')
|
_LOGGER.error('Unknown error occurred while retrieving monitors')
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _shinobi_request(api_path, method='get', data=None):
|
def _shinobi_request(api_path, method='get', data=None):
|
||||||
"""Perform a Shinobi request."""
|
"""Perform a generic request to the Shinobi API."""
|
||||||
|
|
||||||
api_base = SHINOBI['server_origin'] + '/' + SHINOBI['api_key']
|
api_base = SHINOBI['server_origin'] + '/' + SHINOBI['api_key']
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ def _shinobi_request(api_path, method='get', data=None):
|
|||||||
response = req.json()
|
response = req.json()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
_LOGGER.exception('JSON decode exception caught while attempting to '
|
_LOGGER.exception('JSON decode exception caught while attempting to '
|
||||||
'decode "{}"', req.text)
|
'decode "{}"'.format(req.text))
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@@ -91,14 +92,11 @@ def get_all_started_monitors():
|
|||||||
|
|
||||||
get_monitors_path = '/smonitor/' + SHINOBI['group_key']
|
get_monitors_path = '/smonitor/' + SHINOBI['group_key']
|
||||||
|
|
||||||
response = _shinobi_request(get_monitors_path)
|
monitors = _shinobi_request(get_monitors_path)
|
||||||
|
|
||||||
# TODO is it necessary to save monitors globally in SHINOBI?
|
_LOGGER.debug('Shinobi returned {} monitors: {}'.format(str(len(monitors)), str([monitor['name'] for monitor in monitors])))
|
||||||
SHINOBI['monitors'] = response
|
|
||||||
|
|
||||||
_LOGGER.debug('Shinobi returned {} monitors: {}'.format(str(len(SHINOBI['monitors'])), str([monitor['name'] for monitor in SHINOBI['monitors']])))
|
return monitors
|
||||||
|
|
||||||
return SHINOBI['monitors']
|
|
||||||
|
|
||||||
|
|
||||||
def get_monitor_state(monitor_id):
|
def get_monitor_state(monitor_id):
|
||||||
@@ -108,9 +106,9 @@ def get_monitor_state(monitor_id):
|
|||||||
|
|
||||||
|
|
||||||
def set_monitor_state(monitor_id, mode):
|
def set_monitor_state(monitor_id, mode):
|
||||||
"""Get the state of a monitor."""
|
"""Set the state of a monitor."""
|
||||||
if not (mode == SHINOBI_CAM_DISABLED or mode == SHINOBI_CAM_WATCHING or mode == SHINOBI_CAM_RECORDING):
|
if not (mode in SHINOBI_CAM_STATE.values()):
|
||||||
raise ValueError('monitor state must be either {}, {} or {}'.format(SHINOBI_CAM_DISABLED, SHINOBI_CAM_WATCHING, SHINOBI_CAM_RECORDING))
|
raise ValueError('Monitor state must be one of the following values {}.'.format(SHINOBI_CAM_STATE.values()))
|
||||||
api_path = '/monitor/{}/{}'.format(SHINOBI['group_key'], monitor_id)
|
api_path = '/monitor/{}/{}'.format(SHINOBI['group_key'], monitor_id)
|
||||||
return _shinobi_request(api_path)
|
return _shinobi_request(api_path)
|
||||||
|
|
||||||
@@ -121,5 +119,5 @@ def monitor_stream_url(monitor_id):
|
|||||||
|
|
||||||
|
|
||||||
def monitor_still_url(monitor_id):
|
def monitor_still_url(monitor_id):
|
||||||
"""Get the url of still jpg images. Snapshots must be enabled in cam settings, see https://shinobi.video/docs/api#content-get-streams"""
|
"""Get the url of still jpg images. Snapshots must be enabled in cam settings, see https://shinobi.video/docs/api#content-get-streams."""
|
||||||
return SHINOBI['server_origin'] + '/' + SHINOBI['api_key'] + '/jpeg/' + SHINOBI['group_key'] + '/' + monitor_id + '/s.jpg'
|
return SHINOBI['server_origin'] + '/' + SHINOBI['api_key'] + '/jpeg/' + SHINOBI['group_key'] + '/' + monitor_id + '/s.jpg'
|
||||||
|
|||||||
Reference in New Issue
Block a user