mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Refactor nzbget to support future platform changes (#26462)
* Re-factor nzbget platform to enable future features. * Re-factor nzbget platform to enable future features. * Re-factor nzbget platform to enable future features. * Re-factor nzbget platform to enable future features. * Use pynzbgetapi instead of raw HTTP requests * Using pynzbgetapi * Pinning pynzbgetapi version. * Requiring pynzbgetapi 0.2.0 * Addressing review comments * Refreshing requirements (adding pynzbgetapi) * Remove period from logging message * Updating requirements file * Add nzbget init to .coveragerc * Adding nzbget codeowner * Updating codeowners file
This commit is contained in:
parent
9c2053a251
commit
57833f5b1e
@ -436,6 +436,7 @@ omit =
|
||||
homeassistant/components/nuki/lock.py
|
||||
homeassistant/components/nut/sensor.py
|
||||
homeassistant/components/nx584/alarm_control_panel.py
|
||||
homeassistant/components/nzbget/__init__.py
|
||||
homeassistant/components/nzbget/sensor.py
|
||||
homeassistant/components/obihai/*
|
||||
homeassistant/components/octoprint/*
|
||||
|
@ -197,6 +197,7 @@ homeassistant/components/nsw_fuel_station/* @nickw444
|
||||
homeassistant/components/nsw_rural_fire_service_feed/* @exxamalte
|
||||
homeassistant/components/nuki/* @pschmitt
|
||||
homeassistant/components/nws/* @MatthewFlamm
|
||||
homeassistant/components/nzbget/* @chriscla
|
||||
homeassistant/components/obihai/* @dshokouhi
|
||||
homeassistant/components/ohmconnect/* @robbiet480
|
||||
homeassistant/components/onboarding/* @home-assistant/core
|
||||
|
@ -1 +1,106 @@
|
||||
"""The nzbget component."""
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
import pynzbgetapi
|
||||
import requests
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
CONF_PASSWORD,
|
||||
CONF_PORT,
|
||||
CONF_SCAN_INTERVAL,
|
||||
CONF_SSL,
|
||||
CONF_USERNAME,
|
||||
)
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import dispatcher_send
|
||||
from homeassistant.helpers.event import track_time_interval
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = "nzbget"
|
||||
DATA_NZBGET = "data_nzbget"
|
||||
DATA_UPDATED = "nzbget_data_updated"
|
||||
|
||||
DEFAULT_NAME = "NZBGet"
|
||||
DEFAULT_PORT = 6789
|
||||
|
||||
DEFAULT_SCAN_INTERVAL = timedelta(seconds=5)
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_PASSWORD): cv.string,
|
||||
vol.Optional(CONF_USERNAME): cv.string,
|
||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(
|
||||
CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL
|
||||
): cv.time_period,
|
||||
vol.Optional(CONF_SSL, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
},
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up the NZBGet sensors."""
|
||||
host = config[DOMAIN][CONF_HOST]
|
||||
port = config[DOMAIN][CONF_PORT]
|
||||
ssl = "s" if config[DOMAIN][CONF_SSL] else ""
|
||||
name = config[DOMAIN][CONF_NAME]
|
||||
username = config[DOMAIN].get(CONF_USERNAME)
|
||||
password = config[DOMAIN].get(CONF_PASSWORD)
|
||||
scan_interval = config[DOMAIN][CONF_SCAN_INTERVAL]
|
||||
|
||||
try:
|
||||
nzbget_api = pynzbgetapi.NZBGetAPI(host, username, password, ssl, ssl, port)
|
||||
nzbget_api.version()
|
||||
except pynzbgetapi.NZBGetAPIException as conn_err:
|
||||
_LOGGER.error("Error setting up NZBGet API: %s", conn_err)
|
||||
return False
|
||||
|
||||
_LOGGER.debug("Successfully validated NZBGet API connection")
|
||||
|
||||
nzbget_data = hass.data[DATA_NZBGET] = NZBGetData(hass, nzbget_api)
|
||||
nzbget_data.update()
|
||||
|
||||
def refresh(event_time):
|
||||
"""Get the latest data from NZBGet."""
|
||||
nzbget_data.update()
|
||||
|
||||
track_time_interval(hass, refresh, scan_interval)
|
||||
|
||||
sensorconfig = {"client_name": name}
|
||||
|
||||
hass.helpers.discovery.load_platform("sensor", DOMAIN, sensorconfig, config)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class NZBGetData:
|
||||
"""Get the latest data and update the states."""
|
||||
|
||||
def __init__(self, hass, api):
|
||||
"""Initialize the NZBGet RPC API."""
|
||||
self.hass = hass
|
||||
self.status = None
|
||||
self.available = True
|
||||
self._api = api
|
||||
|
||||
def update(self):
|
||||
"""Get the latest data from NZBGet instance."""
|
||||
try:
|
||||
self.status = self._api.status()
|
||||
self.available = True
|
||||
dispatcher_send(self.hass, DATA_UPDATED)
|
||||
except requests.exceptions.ConnectionError:
|
||||
self.available = False
|
||||
_LOGGER.error("Unable to refresh NZBGet data")
|
||||
|
@ -2,7 +2,7 @@
|
||||
"domain": "nzbget",
|
||||
"name": "Nzbget",
|
||||
"documentation": "https://www.home-assistant.io/components/nzbget",
|
||||
"requirements": [],
|
||||
"requirements": ["pynzbgetapi==0.2.0"],
|
||||
"dependencies": [],
|
||||
"codeowners": []
|
||||
"codeowners": ["@chriscla"]
|
||||
}
|
||||
|
@ -1,32 +1,15 @@
|
||||
"""Support for monitoring NZBGet NZB client."""
|
||||
from datetime import timedelta
|
||||
"""Monitor the NZBGet API."""
|
||||
import logging
|
||||
|
||||
from aiohttp.hdrs import CONTENT_TYPE
|
||||
import requests
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||
from homeassistant.const import (
|
||||
CONF_SSL,
|
||||
CONF_HOST,
|
||||
CONF_NAME,
|
||||
CONF_PORT,
|
||||
CONF_PASSWORD,
|
||||
CONF_USERNAME,
|
||||
CONTENT_TYPE_JSON,
|
||||
CONF_MONITORED_VARIABLES,
|
||||
)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
from . import DATA_NZBGET, DATA_UPDATED
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_NAME = "NZBGet"
|
||||
DEFAULT_PORT = 6789
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5)
|
||||
|
||||
SENSOR_TYPES = {
|
||||
"article_cache": ["ArticleCacheMB", "Article Cache", "MB"],
|
||||
@ -40,66 +23,39 @@ SENSOR_TYPES = {
|
||||
"uptime": ["UpTimeSec", "Uptime", "min"],
|
||||
}
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_MONITORED_VARIABLES, default=["download_rate"]): vol.All(
|
||||
cv.ensure_list, [vol.In(SENSOR_TYPES)]
|
||||
),
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_PASSWORD): cv.string,
|
||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
||||
vol.Optional(CONF_SSL, default=False): cv.boolean,
|
||||
vol.Optional(CONF_USERNAME): cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
"""Set up the NZBGet sensors."""
|
||||
host = config.get(CONF_HOST)
|
||||
port = config.get(CONF_PORT)
|
||||
ssl = "s" if config.get(CONF_SSL) else ""
|
||||
name = config.get(CONF_NAME)
|
||||
username = config.get(CONF_USERNAME)
|
||||
password = config.get(CONF_PASSWORD)
|
||||
monitored_types = config.get(CONF_MONITORED_VARIABLES)
|
||||
"""Create NZBGet sensors."""
|
||||
|
||||
url = f"http{ssl}://{host}:{port}/jsonrpc"
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
try:
|
||||
nzbgetapi = NZBGetAPI(api_url=url, username=username, password=password)
|
||||
nzbgetapi.update()
|
||||
except (
|
||||
requests.exceptions.ConnectionError,
|
||||
requests.exceptions.HTTPError,
|
||||
) as conn_err:
|
||||
_LOGGER.error("Error setting up NZBGet API: %s", conn_err)
|
||||
return False
|
||||
nzbget_data = hass.data[DATA_NZBGET]
|
||||
name = discovery_info["client_name"]
|
||||
|
||||
devices = []
|
||||
for ng_type in monitored_types:
|
||||
for sensor_type, sensor_config in SENSOR_TYPES.items():
|
||||
new_sensor = NZBGetSensor(
|
||||
api=nzbgetapi, sensor_type=SENSOR_TYPES.get(ng_type), client_name=name
|
||||
nzbget_data, sensor_type, name, sensor_config[0], sensor_config[1]
|
||||
)
|
||||
devices.append(new_sensor)
|
||||
|
||||
add_entities(devices)
|
||||
add_entities(devices, True)
|
||||
|
||||
|
||||
class NZBGetSensor(Entity):
|
||||
"""Representation of a NZBGet sensor."""
|
||||
|
||||
def __init__(self, api, sensor_type, client_name):
|
||||
def __init__(
|
||||
self, nzbget_data, sensor_type, client_name, sensor_name, unit_of_measurement
|
||||
):
|
||||
"""Initialize a new NZBGet sensor."""
|
||||
self._name = "{} {}".format(client_name, sensor_type[1])
|
||||
self.type = sensor_type[0]
|
||||
self._name = f"{client_name} {sensor_type}"
|
||||
self.type = sensor_name
|
||||
self.client_name = client_name
|
||||
self.api = api
|
||||
self.nzbget_data = nzbget_data
|
||||
self._state = None
|
||||
self._unit_of_measurement = sensor_type[2]
|
||||
self.update()
|
||||
_LOGGER.debug("Created NZBGet sensor: %s", self.type)
|
||||
self._unit_of_measurement = unit_of_measurement
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@ -116,21 +72,31 @@ class NZBGetSensor(Entity):
|
||||
"""Return the unit of measurement of this entity, if any."""
|
||||
return self._unit_of_measurement
|
||||
|
||||
@property
|
||||
def available(self):
|
||||
"""Return whether the sensor is available."""
|
||||
return self.nzbget_data.available
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Handle entity which will be added."""
|
||||
async_dispatcher_connect(
|
||||
self.hass, DATA_UPDATED, self._schedule_immediate_update
|
||||
)
|
||||
|
||||
@callback
|
||||
def _schedule_immediate_update(self):
|
||||
self.async_schedule_update_ha_state(True)
|
||||
|
||||
def update(self):
|
||||
"""Update state of sensor."""
|
||||
try:
|
||||
self.api.update()
|
||||
except requests.exceptions.ConnectionError:
|
||||
# Error calling the API, already logged in api.update()
|
||||
return
|
||||
|
||||
if self.api.status is None:
|
||||
if self.nzbget_data.status is None:
|
||||
_LOGGER.debug(
|
||||
"Update of %s requested, but no status is available", self._name
|
||||
)
|
||||
return
|
||||
|
||||
value = self.api.status.get(self.type)
|
||||
value = self.nzbget_data.status.get(self.type)
|
||||
if value is None:
|
||||
_LOGGER.warning("Unable to locate value for %s", self.type)
|
||||
return
|
||||
@ -143,48 +109,3 @@ class NZBGetSensor(Entity):
|
||||
self._state = round(value / 60, 2)
|
||||
else:
|
||||
self._state = value
|
||||
|
||||
|
||||
class NZBGetAPI:
|
||||
"""Simple JSON-RPC wrapper for NZBGet's API."""
|
||||
|
||||
def __init__(self, api_url, username=None, password=None):
|
||||
"""Initialize NZBGet API and set headers needed later."""
|
||||
self.api_url = api_url
|
||||
self.status = None
|
||||
self.headers = {CONTENT_TYPE: CONTENT_TYPE_JSON}
|
||||
|
||||
if username is not None and password is not None:
|
||||
self.auth = (username, password)
|
||||
else:
|
||||
self.auth = None
|
||||
self.update()
|
||||
|
||||
def post(self, method, params=None):
|
||||
"""Send a POST request and return the response as a dict."""
|
||||
payload = {"method": method}
|
||||
|
||||
if params:
|
||||
payload["params"] = params
|
||||
try:
|
||||
response = requests.post(
|
||||
self.api_url,
|
||||
json=payload,
|
||||
auth=self.auth,
|
||||
headers=self.headers,
|
||||
timeout=5,
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.exceptions.ConnectionError as conn_exc:
|
||||
_LOGGER.error(
|
||||
"Failed to update NZBGet status from %s. Error: %s",
|
||||
self.api_url,
|
||||
conn_exc,
|
||||
)
|
||||
raise
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
"""Update cached response."""
|
||||
self.status = self.post("status")["result"]
|
||||
|
@ -1347,6 +1347,9 @@ pynws==0.7.4
|
||||
# homeassistant.components.nx584
|
||||
pynx584==0.4
|
||||
|
||||
# homeassistant.components.nzbget
|
||||
pynzbgetapi==0.2.0
|
||||
|
||||
# homeassistant.components.obihai
|
||||
pyobihai==1.0.2
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user