Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 2 commits into from
Feb 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 59 additions & 57 deletions homeassistant/components/sensor/sabnzbd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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

Expand All @@ -18,13 +19,10 @@
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'
Expand Down Expand Up @@ -54,38 +52,42 @@
})


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'])
monitored = config.get(CONF_MONITORED_VARIABLES)
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))
@asyncio.coroutine
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def async_update_queue(sab_api):
"""
Throttled function to update SABnzbd queue.

add_devices(devices)
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, add_devices, sab_api):
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
Expand All @@ -95,36 +97,35 @@ 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."""
conf = load_json(hass.config.path(CONFIG_FILE))
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

Expand All @@ -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
Expand All @@ -184,35 +186,35 @@ def unit_of_measurement(self):
"""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")

def update(self):
from pysabnzbd import SabnzbdApiException
try:
yield from async_update_queue(self.sabnzbd_api)
except SabnzbdApiException:
_LOGGER.exception("Connection to SABnzbd API failed")

@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'
6 changes: 3 additions & 3 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,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

Expand Down Expand Up @@ -848,6 +845,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

Expand Down