Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
71 changes: 21 additions & 50 deletions homeassistant/components/sensor/transmission.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@
CONF_USERNAME, STATE_IDLE)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle
from homeassistant.exceptions import PlatformNotReady

REQUIREMENTS = ['transmissionrpc==0.11']
DEPENDENCIES = ['transmission']
DATA_TRANSMISSION = 'TRANSMISSION'
Comment thread
MatteGary marked this conversation as resolved.
Outdated

_LOGGER = logging.getLogger(__name__)

Expand All @@ -32,13 +31,15 @@
'paused_torrents': ['Paused Torrents', None],
'total_torrents': ['Total Torrents', None],
'upload_speed': ['Up Speed', 'MB/s'],
'completed_torrents': ['Completed Torrents', None],
'started_torrents': ['Started Torrents', None],
}

SCAN_INTERVAL = timedelta(minutes=2)

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
Comment thread
MatteGary marked this conversation as resolved.
Outdated
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_MONITORED_VARIABLES, default=['torrents']):
vol.Optional(CONF_MONITORED_VARIABLES):
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PASSWORD): cv.string,
Expand All @@ -49,39 +50,22 @@

def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Transmission sensors."""
import transmissionrpc
from transmissionrpc.error import TransmissionError

name = config.get(CONF_NAME)
host = config.get(CONF_HOST)
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
port = config.get(CONF_PORT)

try:
transmission = transmissionrpc.Client(
host, port=port, user=username, password=password)
transmission_api = TransmissionData(transmission)
except TransmissionError as error:
if str(error).find("401: Unauthorized"):
_LOGGER.error("Credentials for Transmission client are not valid")
return

_LOGGER.warning(
"Unable to connect to Transmission client: %s:%s", host, port)
raise PlatformNotReady

Comment thread
MatteGary marked this conversation as resolved.
transmission_api = hass.data[DATA_TRANSMISSION]
monitored_variables = discovery_info['sensors']
name = discovery_info['client_name']

dev = []
for variable in config[CONF_MONITORED_VARIABLES]:
dev.append(TransmissionSensor(variable, transmission_api, name))
for variable in monitored_variables:
Comment thread
MatteGary marked this conversation as resolved.
Outdated
dev.append(TransmissionSensor(variable, transmission_api, name, hass))

add_entities(dev, True)


class TransmissionSensor(Entity):
"""Representation of a Transmission sensor."""

def __init__(self, sensor_type, transmission_api, client_name):
def __init__(self, sensor_type, transmission_api, client_name, hass):
Comment thread
MatteGary marked this conversation as resolved.
Outdated
"""Initialize the sensor."""
self._name = SENSOR_TYPES[sensor_type][0]
self._state = None
Expand All @@ -90,6 +74,8 @@ def __init__(self, sensor_type, transmission_api, client_name):
self._data = None
self.client_name = client_name
self.type = sensor_type
self.started_torrents = []
self.first_run = True
Comment thread
MatteGary marked this conversation as resolved.
Outdated

@property
def name(self):
Expand All @@ -116,6 +102,13 @@ def update(self):
self._transmission_api.update()
self._data = self._transmission_api.data

if self.type == 'completed_torrents':
self._state = self._transmission_api.getCompletedTorrentCount()
elif self.type == 'started_torrents':
self._state = self._transmission_api.getStartedTorrentCount()

self.first_run = False

if self.type == 'current_status':
if self._data:
upload = self._data.uploadSpeed
Expand Down Expand Up @@ -146,25 +139,3 @@ def update(self):
self._state = self._data.pausedTorrentCount
elif self.type == 'total_torrents':
self._state = self._data.torrentCount


class TransmissionData:
"""Get the latest data and update the states."""

def __init__(self, api):
"""Initialize the Transmission data object."""
self.data = None
self.available = True
self._api = api

@Throttle(SCAN_INTERVAL)
def update(self):
"""Get the latest data from Transmission instance."""
from transmissionrpc.error import TransmissionError

try:
self.data = self._api.session_stats()
self.available = True
except TransmissionError:
self.available = False
_LOGGER.error("Unable to connect to Transmission client")
171 changes: 171 additions & 0 deletions homeassistant/components/transmission.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
"""
Component for monitoring the Transmission BitTorrent client API.

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/transmission/
"""
from datetime import timedelta
import logging
import voluptuous as vol
Comment thread
MatteGary marked this conversation as resolved.
import homeassistant.helpers.config_validation as cv
Comment thread
MatteGary marked this conversation as resolved.
Outdated
from homeassistant.util import Throttle
Comment thread
MatteGary marked this conversation as resolved.
Outdated
from homeassistant.exceptions import PlatformNotReady
Comment thread
MatteGary marked this conversation as resolved.
Outdated
from homeassistant.helpers.event import track_time_interval
from homeassistant.helpers.discovery import load_platform
Comment thread
MatteGary marked this conversation as resolved.
Outdated
from homeassistant.const import (CONF_HOST, CONF_PASSWORD, CONF_NAME,
CONF_PORT, CONF_USERNAME,
CONF_MONITORED_VARIABLES)

REQUIREMENTS = ['transmissionrpc==0.11']
_LOGGER = logging.getLogger(__name__)

DOMAIN = 'transmission'
DATA_TRANSMISSION = 'TRANSMISSION'
Comment thread
MatteGary marked this conversation as resolved.
Outdated

DEFAULT_NAME = 'Transmission'
DEFAULT_PORT = 9091

SENSOR_TYPES = {
'active_torrents': ['Active Torrents', None],
'current_status': ['Status', None],
'download_speed': ['Down Speed', 'MB/s'],
'paused_torrents': ['Paused Torrents', None],
'total_torrents': ['Total Torrents', None],
'upload_speed': ['Up Speed', 'MB/s'],
'completed_torrents': ['Completed Torrents', None],
'started_torrents': ['Started Torrents', None],
}

CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(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_MONITORED_VARIABLES, default=['current_status']):
Comment thread
MatteGary marked this conversation as resolved.
Outdated
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
})
}, extra=vol.ALLOW_EXTRA)

SCAN_INTERVAL = timedelta(minutes=2)
Comment thread
MatteGary marked this conversation as resolved.


def setup(hass, config):
Comment thread
MatteGary marked this conversation as resolved.
hass.data[DATA_TRANSMISSION] = TransmissionData(hass, config)
Comment thread
MatteGary marked this conversation as resolved.
Outdated

def refresh(event_time):
Comment thread
MatteGary marked this conversation as resolved.
hass.data[DATA_TRANSMISSION].update()

track_time_interval(hass, refresh, SCAN_INTERVAL)

sensorconfig = {
'sensors': config[DOMAIN].get(CONF_MONITORED_VARIABLES),
'client_name': config[DOMAIN].get(CONF_NAME)}
load_platform(hass, 'sensor', DOMAIN, sensorconfig)

_LOGGER.info("Transmission component setup completed.")
Comment thread
MatteGary marked this conversation as resolved.
Outdated
return True


class TransmissionData:
Comment thread
MatteGary marked this conversation as resolved.
"""Get the latest data and update the states."""

def __init__(self, hass, config):
import transmissionrpc
from transmissionrpc.error import TransmissionError
try:
"""Initialize the Transmission RPC API"""
Comment thread
MatteGary marked this conversation as resolved.
Outdated
host = config[DOMAIN].get(CONF_HOST)
Comment thread
MatteGary marked this conversation as resolved.
Outdated
username = config[DOMAIN].get(CONF_USERNAME)
password = config[DOMAIN].get(CONF_PASSWORD)
port = config[DOMAIN].get(CONF_PORT)

api = transmissionrpc.Client(
Comment thread
MatteGary marked this conversation as resolved.
Outdated
host, port=port, user=username, password=password)

"""Initialize the Transmission data object."""
Comment thread
MatteGary marked this conversation as resolved.
Outdated
self.data = None
self.torrents = None
self.available = True
self._api = api
self.completed_torrents = []
self.started_torrents = []
self.initTorrentList()
Comment thread
MatteGary marked this conversation as resolved.
Outdated
self.hass = hass

except TransmissionError as error:
Comment thread
MatteGary marked this conversation as resolved.
Outdated
if str(error).find("401: Unauthorized"):
_LOGGER.error("Credentials for"
" Transmission client are not valid")
return

_LOGGER.warning(
"Unable to connect to Transmission client: %s:%s", host, port)
raise PlatformNotReady
Comment thread
MatteGary marked this conversation as resolved.
Outdated

@Throttle(SCAN_INTERVAL)
def update(self):
"""Get the latest data from Transmission instance."""
from transmissionrpc.error import TransmissionError

try:
self.data = self._api.session_stats()
self.torrents = self._api.get_torrents()

self.checkCompletedTorrent()
self.checkStartedTorrent()

_LOGGER.info("Torrent Data updated")
Comment thread
MatteGary marked this conversation as resolved.
Outdated
self.available = True
except TransmissionError:
self.available = False
_LOGGER.error("Unable to connect to Transmission client")

def initTorrentList(self):
self.torrents = self._api.get_torrents()
self.completed_torrents = [
x.name for x in self.torrents if x.status == "seeding"]
self.started_torrents = [
x.name for x in self.torrents if x.status == "downloading"]

def checkCompletedTorrent(self):
"""Get completed torrent functionality"""
actual_torrents = self.torrents
actual_completed_torrents = [
var.name for var in actual_torrents if var.status == "seeding"]

tmp_completed_torrents = list(
set(actual_completed_torrents).difference(
self.completed_torrents))
if tmp_completed_torrents:
Comment thread
MatteGary marked this conversation as resolved.
Outdated
for var in tmp_completed_torrents:
_LOGGER.info("Completed Torrent found")
Comment thread
MatteGary marked this conversation as resolved.
Outdated
self.hass.bus.fire(
'transmission_downloaded_torrent', {
'name': var})

self.completed_torrents = actual_completed_torrents

def checkStartedTorrent(self):
"""Get started torrent functionality"""
Comment thread
MatteGary marked this conversation as resolved.
Outdated
actual_torrents = self.torrents
actual_started_torrents = [
var.name for var
in actual_torrents if var.status == "downloading"]

tmp_started_torrents = list(
set(actual_started_torrents).difference(
self.started_torrents))
if tmp_started_torrents:
Comment thread
MatteGary marked this conversation as resolved.
Outdated
for var in tmp_started_torrents:
self.hass.bus.fire(
'transmission_started_torrent', {
'name': var})
self.started_torrents = actual_started_torrents

def getStartedTorrentCount(self):
Comment thread
MatteGary marked this conversation as resolved.
Outdated
return len(self.started_torrents)

def getCompletedTorrentCount(self):
return len(self.completed_torrents)