Make HA discover sabnzbd and add it to the Configurator (#8634)

* Init discover sab.

* Fix hound errors

Nobody likes being hound at :(

* sabnzbd discovery says if ssl is active.

* Fixups after codereview.
This commit is contained in:
Hellowlol 2017-08-04 23:24:55 +02:00 committed by Fabian Affolter
parent 77cdc833f0
commit cf298c2435
2 changed files with 110 additions and 20 deletions

View File

@ -59,6 +59,7 @@ SERVICE_HANDLERS = {
'frontier_silicon': ('media_player', 'frontier_silicon'), 'frontier_silicon': ('media_player', 'frontier_silicon'),
'openhome': ('media_player', 'openhome'), 'openhome': ('media_player', 'openhome'),
'harmony': ('remote', 'harmony'), 'harmony': ('remote', 'harmony'),
'sabnzbd': ('sensor', 'sabnzbd'),
'bose_soundtouch': ('media_player', 'soundtouch'), 'bose_soundtouch': ('media_player', 'soundtouch'),
'bluesound': ('media_player', 'bluesound'), 'bluesound': ('media_player', 'bluesound'),
} }

View File

@ -4,7 +4,9 @@ Support for monitoring an SABnzbd NZB client.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.sabnzbd/ https://home-assistant.io/components/sensor.sabnzbd/
""" """
import os
import logging import logging
import json
from datetime import timedelta from datetime import timedelta
import voluptuous as vol import voluptuous as vol
@ -16,14 +18,17 @@ from homeassistant.const import (
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle from homeassistant.util import Throttle
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.loader import get_component
REQUIREMENTS = ['https://github.com/jamespcole/home-assistant-nzb-clients/' REQUIREMENTS = ['https://github.com/jamespcole/home-assistant-nzb-clients/'
'archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip' 'archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip'
'#python-sabnzbd==0.1'] '#python-sabnzbd==0.1']
_CONFIGURING = {}
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
_THROTTLED_REFRESH = None _THROTTLED_REFRESH = None
CONFIG_FILE = 'sabnzbd.conf'
DEFAULT_NAME = 'SABnzbd' DEFAULT_NAME = 'SABnzbd'
DEFAULT_PORT = 8080 DEFAULT_PORT = 8080
DEFAULT_SSL = False DEFAULT_SSL = False
@ -50,31 +55,24 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
}) })
def setup_platform(hass, config, add_devices, discovery_info=None): def _check_sabnzbd(sab_api, base_url, api_key):
"""Set up the SABnzbd sensors.""" """Check if we can reach SABnzbd."""
from pysabnzbd import SabnzbdApi, SabnzbdApiException from pysabnzbd import SabnzbdApiException
sab_api = sab_api(base_url, api_key)
host = config.get(CONF_HOST)
port = config.get(CONF_PORT)
name = config.get(CONF_NAME)
api_key = config.get(CONF_API_KEY)
monitored_types = config.get(CONF_MONITORED_VARIABLES)
use_ssl = config.get(CONF_SSL)
if use_ssl:
uri_scheme = 'https://'
else:
uri_scheme = 'http://'
base_url = "{}{}:{}/".format(uri_scheme, host, port)
sab_api = SabnzbdApi(base_url, api_key)
try: try:
sab_api.check_available() sab_api.check_available()
except SabnzbdApiException: except SabnzbdApiException:
_LOGGER.error("Connection to SABnzbd API failed") _LOGGER.error("Connection to SABnzbd API failed")
return False return False
return True
def setup_sabnzbd(base_url, apikey, name, hass, config, add_devices, sab_api):
"""Set up polling from SABnzbd and sensors."""
sab_api = sab_api(base_url, apikey)
# Add minimal info to the front end
monitored = config.get(CONF_MONITORED_VARIABLES, ['current_status'])
# pylint: disable=global-statement # pylint: disable=global-statement
global _THROTTLED_REFRESH global _THROTTLED_REFRESH
@ -82,12 +80,84 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
MIN_TIME_BETWEEN_UPDATES)(sab_api.refresh_queue) MIN_TIME_BETWEEN_UPDATES)(sab_api.refresh_queue)
devices = [] devices = []
for variable in monitored_types: for variable in monitored:
devices.append(SabnzbdSensor(variable, sab_api, name)) devices.append(SabnzbdSensor(variable, sab_api, name))
add_devices(devices) add_devices(devices)
def request_configuration(host, name, hass, config, add_devices, sab_api):
"""Request configuration steps from the user."""
configurator = get_component('configurator')
# We got an error if this method is called while we are configuring
if host in _CONFIGURING:
configurator.notify_errors(_CONFIGURING[host],
'Failed to register, please try again.')
return
def sabnzbd_configuration_callback(data):
"""Handle configuration changes."""
api_key = data.get('api_key')
if _check_sabnzbd(sab_api, host, api_key):
setup_sabnzbd(host, api_key, name,
hass, config, add_devices, sab_api)
def success():
"""Set up was successful."""
conf = _read_config(hass)
conf[host] = {'api_key': api_key}
_write_config(hass, conf)
req_config = _CONFIGURING.pop(host)
hass.async_add_job(configurator.request_done, req_config)
hass.async_add_job(success)
_CONFIGURING[host] = configurator.request_config(
hass,
DEFAULT_NAME,
sabnzbd_configuration_callback,
description=('Enter the API Key'),
submit_caption='Confirm',
fields=[{
'id': 'api_key',
'name': 'API Key',
'type': ''}]
)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up the SABnzbd platform."""
from pysabnzbd import SabnzbdApi
host = config.get(CONF_HOST) or discovery_info.get(CONF_HOST)
port = config.get(CONF_PORT) or discovery_info.get(CONF_PORT)
name = config.get(CONF_NAME, DEFAULT_NAME)
use_ssl = DEFAULT_SSL
if config.get(CONF_SSL):
use_ssl = True
elif discovery_info.get('properties', {}).get('https', '0') == '1':
use_ssl = True
uri_scheme = 'https://' if use_ssl else 'http://'
base_url = "{}{}:{}/".format(uri_scheme, host, port)
api_key = config.get(CONF_API_KEY)
if not api_key:
conf = _read_config(hass)
if conf.get(base_url, {}).get('api_key'):
api_key = conf[base_url]['api_key']
if not _check_sabnzbd(SabnzbdApi, base_url, api_key):
request_configuration(base_url, name, hass, config,
add_devices, SabnzbdApi)
return
setup_sabnzbd(base_url, api_key, name, hass,
config, add_devices, SabnzbdApi)
class SabnzbdSensor(Entity): class SabnzbdSensor(Entity):
"""Representation of an SABnzbd sensor.""" """Representation of an SABnzbd sensor."""
@ -145,3 +215,22 @@ class SabnzbdSensor(Entity):
self._state = self.sabnzb_client.queue.get('diskspace1') self._state = self.sabnzb_client.queue.get('diskspace1')
else: else:
self._state = 'Unknown' self._state = 'Unknown'
def _read_config(hass):
"""Read SABnzbd config."""
path = hass.config.path(CONFIG_FILE)
if not os.path.isfile(path):
return {}
with open(path) as f_handle:
# Guard against empty file
return json.loads(f_handle.read() or '{}')
def _write_config(hass, config):
"""Write SABnzbd config."""
data = json.dumps(config)
with open(hass.config.path(CONFIG_FILE), 'w', encoding='utf-8') as outfile:
outfile.write(data)