Help with NZBGet Switch Component

I have been working on a new NZBGet Switch Component to allow the Pause and Resume functions for downloads. As I am not much of a coder so I have found myself stuck at a point where the switch only partially works. I can confirm when booting up Home Assistant the switch will show the correct status of On/Off although it doesn’t update and the toggle doesn’t work as it should. The core code including the JSON-RPC wrapper has been taken from the NZBGet Sensor Component.

API Reference: https://nzbget.net/api/

nzbget.py


from datetime import timedelta
import logging

from aiohttp.hdrs import CONTENT_TYPE
import requests
import voluptuous as vol

from homeassistant.components.switch import PLATFORM_SCHEMA
from homeassistant.const import (
    CONF_SSL, CONF_HOST, CONF_NAME, CONF_PORT, CONF_PASSWORD, CONF_USERNAME,
    CONTENT_TYPE_JSON, STATE_OFF, STATE_ON)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import ToggleEntity
from homeassistant.util import Throttle

_LOGGING = logging.getLogger(__name__)

DEFAULT_NAME = 'NZBGet Switch'
DEFAULT_PORT = 6789

MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=5)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_HOST): cv.string,
    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,
})


# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
    """Set up the NZBGet switch."""
    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)

    url = "http{}://{}:{}/jsonrpc".format(ssl, host, port)

    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

    add_devices([NZBGetSwitch(nzbgetapi, name)])

class NZBGetSwitch(ToggleEntity):
    """Representation of a NZBGet switch."""

    def __init__(self, api, name):
        """Initialize the NZBGet switch."""
        self._name = name
        self.api = api
        self._state = STATE_OFF

    @property
    def name(self):
        """Return the name of the switch."""
        return self._name

    @property
    def state(self):
        """Return the state of the device."""
        return self._state

    @property
    def is_on(self):
        """Return true if device is on."""
        return self._state == STATE_ON

    def turn_on(self, **kwargs):
        """Turn the device on."""
        self.api.resumedownload()

    def turn_off(self, **kwargs):
        """Turn the device off."""
        self.api.pausedownload()

    def update(self):
        """Get the latest data from deluge and updates the state."""
        active = self.api.status.get("DownloadPaused")
        self._state = STATE_OFF if active else STATE_ON

class NZBGetAPI(object):
    """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.resumedownload = None
        self.pausedownload = 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."""
        try:
            self.status = self.post('status')['result']
        except requests.exceptions.ConnectionError:
            # failed to update status - exception already logged in self.post
            raise
`

Unfortunately I cannot help! Just wanted to say it would be a great component. Being able to set download speed would be great as well. Then one woul be able to lower download when tv on (streaming) when being on adsl broadband for example and setting to full speed again when tv off. For example.

I hope you get this together!

Any news on a working NZBGET switch component ? I don’t have time for the moment but I can send 1 or 2 beer if someone make it official and working like the qbittorrent one :smile:

I’m currently working on it. I have the pause switch working as well as some extra sensors. I just want to add a way to set the rate limiter and I’ll look into getting it pulled into home assistant.

Drop the files here in an nzbget folder in custom_components if you’d like to use it in the meantime. It works the similiarly to the transmission component.

Set the configuration for instance like this:

nzbget:
   host: <your-ip>
   monitored_variables:
     - download_rate
     - download_paused
     - free_disk_space
     - uptime
     - download_limit
 switch:
     - pause_download

Hi,

Many thanks for the link and the work, i’m very busy for the moment but I will give a try very soon :slight_smile: as it’s an super argument to take some time on my home assistant config.

Hi ,

Did you end up getting this merged? Looking to use it myself to pause downloads when I start a PS4 game, then resume when I finish up.

@sophof

^^^^^^

Hey Hansel,
Doesn’t look like sophof has merged it.
If you want to control NZBGet without using a custom component you can also use a command_line switch like below. Replace the username / password / ip address / port number to match your environment.

switch:
  - platform: command_line
      nzbget_pause:
        command_on: "curl -XPOST http://username:[email protected]:0000/jsonrpc -d '{\"method\": \"pausepost\"}' && curl -XPOST http://username:[email protected]:0000/jsonrpc -d '{\"method\": \"pausedownload\"}'"
        command_off: "curl -XPOST http://username:[email protected]:0000/jsonrpc -d '{\"method\": \"scheduleresume\", \"params\": [1]}'"
        command_state: "curl -s http://username:[email protected]:0000/jsonrpc -d '{\"method\": \"status\"}' |grep 'ServerPaused\" : true'"

I use mine to pause when streaming services are opened on my TV and then just resume downloads in the evening.

@Hansel Sadly I didn’t finish it no. I’m having trouble implementing it in the way I want (basically supporting the option to send any command via a service). I asked for some help on the forum but didn’t get any :frowning:

I plan to get back to it, but honestly I was getting a bit frustrated, so it might take a while till I get back to it.

No problem mate, I totally hear you :slight_smile:

@stanvx’s solution above works fine for the time being (thanks for that!)

Has the resume function of the switch stopped working for you? Suddenly stopped working for me the other day.

With Home Assistant release 100 NZBGet has been move into it’s own platform. With this the pause and resume services have been added.

I have adjusted the NZBGet Pause Downloads switch to a template switch. https://github.com/stanvx/Home-Assistant-Configuration/blob/cad28d081b99f6e7d761fc36d2f926a697400dfc/packages/downloads.yaml#L28-L36

1 Like