diff --git a/homeassistant/components/sensor/sabnzbd.py b/homeassistant/components/sensor/sabnzbd.py index 9ce2da09451..632e1ed5c1d 100644 --- a/homeassistant/components/sensor/sabnzbd.py +++ b/homeassistant/components/sensor/sabnzbd.py @@ -4,6 +4,7 @@ Support for monitoring an SABnzbd NZB client. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.sabnzbd/ """ +import asyncio import logging from datetime import timedelta @@ -18,13 +19,10 @@ from homeassistant.util import Throttle from homeassistant.util.json import load_json, save_json import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['https://github.com/jamespcole/home-assistant-nzb-clients/' - 'archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip' - '#python-sabnzbd==0.1'] +REQUIREMENTS = ['pysabnzbd==0.0.3'] _CONFIGURING = {} _LOGGER = logging.getLogger(__name__) -_THROTTLED_REFRESH = None CONFIG_FILE = 'sabnzbd.conf' 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.""" from pysabnzbd import SabnzbdApiException sab_api = sab_api(base_url, api_key) try: - sab_api.check_available() + yield from sab_api.check_available() except SabnzbdApiException: _LOGGER.error("Connection to SABnzbd API failed") return False 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.""" 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 - 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) + monitored = config.get(CONF_MONITORED_VARIABLES) + async_add_devices([SabnzbdSensor(variable, sab_api, name) + for variable in monitored]) -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.""" configurator = hass.components.configurator # 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 - def sabnzbd_configuration_callback(data): + @asyncio.coroutine + def async_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) + if (yield from async_check_sabnzbd(sab_api, host, api_key)): + setup_sabnzbd(host, api_key, name, config, + async_add_devices, sab_api) def success(): """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} save_json(hass.config.path(CONFIG_FILE), conf) 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) - _CONFIGURING[host] = configurator.request_config( + _CONFIGURING[host] = configurator.async_request_config( DEFAULT_NAME, - sabnzbd_configuration_callback, - description=('Enter the API Key'), + async_configuration_callback, + description='Enter the API Key', submit_caption='Confirm', - fields=[{ - 'id': 'api_key', - 'name': 'API Key', - 'type': ''}] + fields=[{'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.""" 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) use_ssl = config.get(CONF_SSL) + api_key = config.get(CONF_API_KEY) + 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 = load_json(hass.config.path(CONFIG_FILE)) if conf.get(base_url, {}).get('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, - add_devices, SabnzbdApi) + async_add_devices, SabnzbdApi) return - setup_sabnzbd(base_url, api_key, name, hass, - config, add_devices, SabnzbdApi) + setup_sabnzbd(base_url, api_key, name, config, + async_add_devices, SabnzbdApi) class SabnzbdSensor(Entity): """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.""" self._name = SENSOR_TYPES[sensor_type][0] - self.sabnzb_client = sabnzb_client + self.sabnzbd_api = sabnzbd_api self.type = sensor_type self.client_name = client_name self._state = None @@ -184,35 +186,35 @@ class SabnzbdSensor(Entity): """Return the unit of measurement of this entity, if any.""" return self._unit_of_measurement - # pylint: disable=no-self-use - def refresh_sabnzbd_data(self): + @asyncio.coroutine + def async_refresh_sabnzbd_data(self): """Call the throttled SABnzbd refresh method.""" - if _THROTTLED_REFRESH is not None: - from pysabnzbd import SabnzbdApiException - try: - _THROTTLED_REFRESH() - except SabnzbdApiException: - _LOGGER.exception("Connection to SABnzbd API failed") + from pysabnzbd import SabnzbdApiException + try: + yield from async_update_queue(self.sabnzbd_api) + except SabnzbdApiException: + _LOGGER.exception("Connection to SABnzbd API failed") - def update(self): + @asyncio.coroutine + def async_update(self): """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': - self._state = self.sabnzb_client.queue.get('status') + self._state = self.sabnzbd_api.queue.get('status') 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) 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': - self._state = self.sabnzb_client.queue.get('mbleft') + self._state = self.sabnzbd_api.queue.get('mbleft') 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': - self._state = self.sabnzb_client.queue.get('diskspace1') + self._state = self.sabnzbd_api.queue.get('diskspace1') elif self.type == 'queue_count': - self._state = self.sabnzb_client.queue.get('noofslots_total') + self._state = self.sabnzbd_api.queue.get('noofslots_total') else: self._state = 'Unknown' diff --git a/requirements_all.txt b/requirements_all.txt index 21ae23ccc3d..5af332fe65b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -373,9 +373,6 @@ https://github.com/jabesq/netatmo-api-python/archive/v0.9.2.1.zip#lnetatmo==0.9. # homeassistant.components.neato 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 https://github.com/mweinelt/anel-pwrctrl/archive/ed26e8830e28a2bfa4260a9002db23ce3e7e63d7.zip#anel_pwrctrl==0.0.1 @@ -846,6 +843,9 @@ pyqwikswitch==0.4 # homeassistant.components.rainbird pyrainbird==0.1.3 +# homeassistant.components.sensor.sabnzbd +pysabnzbd==0.0.3 + # homeassistant.components.climate.sensibo pysensibo==1.0.2