Migrated SABnzbd sensor to asyncio and switched to pypi library (#12290)

* Migrated SABnzbd sensor to asyncio and switched to pypi library

* bumped pysabnzbd version and refactored imports
This commit is contained in:
Jerad Meisner 2018-02-11 09:33:56 -08:00 committed by Paulus Schoutsen
parent 26209de2f2
commit 6c358fa6a3
2 changed files with 64 additions and 62 deletions

View File

@ -4,6 +4,7 @@ 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 asyncio
import logging import logging
from datetime import timedelta from datetime import timedelta
@ -18,13 +19,10 @@ from homeassistant.util import Throttle
from homeassistant.util.json import load_json, save_json from homeassistant.util.json import load_json, save_json
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['https://github.com/jamespcole/home-assistant-nzb-clients/' REQUIREMENTS = ['pysabnzbd==0.0.3']
'archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip'
'#python-sabnzbd==0.1']
_CONFIGURING = {} _CONFIGURING = {}
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
_THROTTLED_REFRESH = None
CONFIG_FILE = 'sabnzbd.conf' CONFIG_FILE = 'sabnzbd.conf'
DEFAULT_NAME = 'SABnzbd' DEFAULT_NAME = 'SABnzbd'
@ -54,38 +52,42 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
}) })
def _check_sabnzbd(sab_api, base_url, api_key): @asyncio.coroutine
def async_check_sabnzbd(sab_api, base_url, api_key):
"""Check if we can reach SABnzbd.""" """Check if we can reach SABnzbd."""
from pysabnzbd import SabnzbdApiException from pysabnzbd import SabnzbdApiException
sab_api = sab_api(base_url, api_key) sab_api = sab_api(base_url, api_key)
try: try:
sab_api.check_available() yield from 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 return True
def setup_sabnzbd(base_url, apikey, name, hass, config, add_devices, sab_api): def setup_sabnzbd(base_url, apikey, name, config,
async_add_devices, sab_api):
"""Set up polling from SABnzbd and sensors.""" """Set up polling from SABnzbd and sensors."""
sab_api = sab_api(base_url, apikey) sab_api = sab_api(base_url, apikey)
# Add minimal info to the front end monitored = config.get(CONF_MONITORED_VARIABLES)
monitored = config.get(CONF_MONITORED_VARIABLES, ['current_status']) async_add_devices([SabnzbdSensor(variable, sab_api, name)
for variable in monitored])
# pylint: disable=global-statement
global _THROTTLED_REFRESH
_THROTTLED_REFRESH = Throttle(
MIN_TIME_BETWEEN_UPDATES)(sab_api.refresh_queue)
devices = []
for variable in monitored:
devices.append(SabnzbdSensor(variable, sab_api, name))
add_devices(devices)
def request_configuration(host, name, hass, config, add_devices, sab_api): @asyncio.coroutine
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def async_update_queue(sab_api):
"""
Throttled function to update SABnzbd queue.
This ensures that the queue info only gets updated once for all sensors
"""
yield from sab_api.refresh_queue()
def request_configuration(host, name, hass, config, async_add_devices,
sab_api):
"""Request configuration steps from the user.""" """Request configuration steps from the user."""
configurator = hass.components.configurator configurator = hass.components.configurator
# We got an error if this method is called while we are configuring # We got an error if this method is called while we are configuring
@ -95,12 +97,13 @@ def request_configuration(host, name, hass, config, add_devices, sab_api):
return return
def sabnzbd_configuration_callback(data): @asyncio.coroutine
def async_configuration_callback(data):
"""Handle configuration changes.""" """Handle configuration changes."""
api_key = data.get('api_key') api_key = data.get('api_key')
if _check_sabnzbd(sab_api, host, api_key): if (yield from async_check_sabnzbd(sab_api, host, api_key)):
setup_sabnzbd(host, api_key, name, setup_sabnzbd(host, api_key, name, config,
hass, config, add_devices, sab_api) async_add_devices, sab_api)
def success(): def success():
"""Set up was successful.""" """Set up was successful."""
@ -108,23 +111,21 @@ def request_configuration(host, name, hass, config, add_devices, sab_api):
conf[host] = {'api_key': api_key} conf[host] = {'api_key': api_key}
save_json(hass.config.path(CONFIG_FILE), conf) save_json(hass.config.path(CONFIG_FILE), conf)
req_config = _CONFIGURING.pop(host) req_config = _CONFIGURING.pop(host)
hass.async_add_job(configurator.request_done, req_config) configurator.async_request_done(req_config)
hass.async_add_job(success) hass.async_add_job(success)
_CONFIGURING[host] = configurator.request_config( _CONFIGURING[host] = configurator.async_request_config(
DEFAULT_NAME, DEFAULT_NAME,
sabnzbd_configuration_callback, async_configuration_callback,
description=('Enter the API Key'), description='Enter the API Key',
submit_caption='Confirm', submit_caption='Confirm',
fields=[{ fields=[{'id': 'api_key', 'name': 'API Key', 'type': ''}]
'id': 'api_key',
'name': 'API Key',
'type': ''}]
) )
def setup_platform(hass, config, add_devices, discovery_info=None): @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the SABnzbd platform.""" """Set up the SABnzbd platform."""
from pysabnzbd import SabnzbdApi from pysabnzbd import SabnzbdApi
@ -139,31 +140,32 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
name = config.get(CONF_NAME, DEFAULT_NAME) name = config.get(CONF_NAME, DEFAULT_NAME)
use_ssl = config.get(CONF_SSL) use_ssl = config.get(CONF_SSL)
api_key = config.get(CONF_API_KEY)
uri_scheme = 'https://' if use_ssl else 'http://' uri_scheme = 'https://' if use_ssl else 'http://'
base_url = "{}{}:{}/".format(uri_scheme, host, port) base_url = "{}{}:{}/".format(uri_scheme, host, port)
api_key = config.get(CONF_API_KEY)
if not api_key: if not api_key:
conf = load_json(hass.config.path(CONFIG_FILE)) conf = load_json(hass.config.path(CONFIG_FILE))
if conf.get(base_url, {}).get('api_key'): if conf.get(base_url, {}).get('api_key'):
api_key = conf[base_url]['api_key'] api_key = conf[base_url]['api_key']
if not _check_sabnzbd(SabnzbdApi, base_url, api_key): if not (yield from async_check_sabnzbd(SabnzbdApi, base_url, api_key)):
request_configuration(base_url, name, hass, config, request_configuration(base_url, name, hass, config,
add_devices, SabnzbdApi) async_add_devices, SabnzbdApi)
return return
setup_sabnzbd(base_url, api_key, name, hass, setup_sabnzbd(base_url, api_key, name, config,
config, add_devices, SabnzbdApi) async_add_devices, SabnzbdApi)
class SabnzbdSensor(Entity): class SabnzbdSensor(Entity):
"""Representation of an SABnzbd sensor.""" """Representation of an SABnzbd sensor."""
def __init__(self, sensor_type, sabnzb_client, client_name): def __init__(self, sensor_type, sabnzbd_api, client_name):
"""Initialize the sensor.""" """Initialize the sensor."""
self._name = SENSOR_TYPES[sensor_type][0] self._name = SENSOR_TYPES[sensor_type][0]
self.sabnzb_client = sabnzb_client self.sabnzbd_api = sabnzbd_api
self.type = sensor_type self.type = sensor_type
self.client_name = client_name self.client_name = client_name
self._state = None self._state = None
@ -184,35 +186,35 @@ class SabnzbdSensor(Entity):
"""Return the unit of measurement of this entity, if any.""" """Return the unit of measurement of this entity, if any."""
return self._unit_of_measurement return self._unit_of_measurement
# pylint: disable=no-self-use @asyncio.coroutine
def refresh_sabnzbd_data(self): def async_refresh_sabnzbd_data(self):
"""Call the throttled SABnzbd refresh method.""" """Call the throttled SABnzbd refresh method."""
if _THROTTLED_REFRESH is not None:
from pysabnzbd import SabnzbdApiException from pysabnzbd import SabnzbdApiException
try: try:
_THROTTLED_REFRESH() yield from async_update_queue(self.sabnzbd_api)
except SabnzbdApiException: except SabnzbdApiException:
_LOGGER.exception("Connection to SABnzbd API failed") _LOGGER.exception("Connection to SABnzbd API failed")
def update(self): @asyncio.coroutine
def async_update(self):
"""Get the latest data and updates the states.""" """Get the latest data and updates the states."""
self.refresh_sabnzbd_data() yield from self.async_refresh_sabnzbd_data()
if self.sabnzb_client.queue: if self.sabnzbd_api.queue:
if self.type == 'current_status': if self.type == 'current_status':
self._state = self.sabnzb_client.queue.get('status') self._state = self.sabnzbd_api.queue.get('status')
elif self.type == 'speed': elif self.type == 'speed':
mb_spd = float(self.sabnzb_client.queue.get('kbpersec')) / 1024 mb_spd = float(self.sabnzbd_api.queue.get('kbpersec')) / 1024
self._state = round(mb_spd, 1) self._state = round(mb_spd, 1)
elif self.type == 'queue_size': elif self.type == 'queue_size':
self._state = self.sabnzb_client.queue.get('mb') self._state = self.sabnzbd_api.queue.get('mb')
elif self.type == 'queue_remaining': elif self.type == 'queue_remaining':
self._state = self.sabnzb_client.queue.get('mbleft') self._state = self.sabnzbd_api.queue.get('mbleft')
elif self.type == 'disk_size': elif self.type == 'disk_size':
self._state = self.sabnzb_client.queue.get('diskspacetotal1') self._state = self.sabnzbd_api.queue.get('diskspacetotal1')
elif self.type == 'disk_free': elif self.type == 'disk_free':
self._state = self.sabnzb_client.queue.get('diskspace1') self._state = self.sabnzbd_api.queue.get('diskspace1')
elif self.type == 'queue_count': elif self.type == 'queue_count':
self._state = self.sabnzb_client.queue.get('noofslots_total') self._state = self.sabnzbd_api.queue.get('noofslots_total')
else: else:
self._state = 'Unknown' self._state = 'Unknown'

View File

@ -373,9 +373,6 @@ https://github.com/jabesq/netatmo-api-python/archive/v0.9.2.1.zip#lnetatmo==0.9.
# homeassistant.components.neato # homeassistant.components.neato
https://github.com/jabesq/pybotvac/archive/v0.0.5.zip#pybotvac==0.0.5 https://github.com/jabesq/pybotvac/archive/v0.0.5.zip#pybotvac==0.0.5
# homeassistant.components.sensor.sabnzbd
https://github.com/jamespcole/home-assistant-nzb-clients/archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip#python-sabnzbd==0.1
# homeassistant.components.switch.anel_pwrctrl # homeassistant.components.switch.anel_pwrctrl
https://github.com/mweinelt/anel-pwrctrl/archive/ed26e8830e28a2bfa4260a9002db23ce3e7e63d7.zip#anel_pwrctrl==0.0.1 https://github.com/mweinelt/anel-pwrctrl/archive/ed26e8830e28a2bfa4260a9002db23ce3e7e63d7.zip#anel_pwrctrl==0.0.1
@ -846,6 +843,9 @@ pyqwikswitch==0.4
# homeassistant.components.rainbird # homeassistant.components.rainbird
pyrainbird==0.1.3 pyrainbird==0.1.3
# homeassistant.components.sensor.sabnzbd
pysabnzbd==0.0.3
# homeassistant.components.climate.sensibo # homeassistant.components.climate.sensibo
pysensibo==1.0.2 pysensibo==1.0.2