From ba13f78d49a1e8c4be485bf645a61c8c1f542964 Mon Sep 17 00:00:00 2001 From: jamespcole Date: Mon, 6 Apr 2015 22:13:04 +1000 Subject: [PATCH 1/3] Added initial Transmission torrent client sensor --- .../components/sensor/transmission.py | 176 ++++++++++++++++++ requirements.txt | 9 +- 2 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 homeassistant/components/sensor/transmission.py diff --git a/homeassistant/components/sensor/transmission.py b/homeassistant/components/sensor/transmission.py new file mode 100644 index 00000000000..5738e791596 --- /dev/null +++ b/homeassistant/components/sensor/transmission.py @@ -0,0 +1,176 @@ +""" +homeassistant.components.sensor.sabnzbd +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Monitors SABnzbd NZB client API + +Configuration: + +To use the SABnzbd sensor you will need to add something like the following to +your config/configuration.yaml + +sensor: + platform: sabnzbd + name: SAB + api_key: YOUR_API_KEY + base_url: YOUR_SABNZBD_BASE_URL + monitored_variables: + - type: 'current_status' + - type: 'speed' + - type: 'queue_size' + - type: 'queue_remaining' + - type: 'disk_size' + - type: 'disk_free' + +VARIABLES: + +base_url +*Required +This is the base URL of your SABnzbd instance including the port number if not +running on 80 +Example: http://192.168.1.32:8124/ + + +name +*Optional +The name to use when displaying this SABnzbd instance + +monitored_variables +*Required +An array specifying the variables to monitor. + +These are the variables for the monitored_variables array: + +type +*Required +The variable you wish to monitor, see the configuration example above for a +list of all available variables + + +""" + +from homeassistant.util import Throttle +from datetime import timedelta +from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD + +from homeassistant.helpers.entity import Entity +# pylint: disable=no-name-in-module, import-error +import transmissionrpc + +from transmissionrpc.error import TransmissionError + +import logging + +SENSOR_TYPES = { + 'current_status': ['Status', ''], + 'download_speed': ['Down Speed', 'MB/s'], + 'upload_speed': ['Up Speed', 'MB/s'], + 'queue_size': ['Queue', 'MB'], + 'queue_remaining': ['Left', 'MB'], + 'disk_size': ['Disk', 'GB'], + 'disk_free': ['Disk Free', 'GB'], +} + +_LOGGER = logging.getLogger(__name__) + +_THROTTLED_REFRESH = None + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """ Sets up the sensors """ + host = config.get(CONF_HOST) + username = config.get(CONF_USERNAME, None) + password = config.get(CONF_PASSWORD, None) + port = config.get('port') + + name = config.get("name", "Transmission") + if not host: + _LOGGER.error('Missing config variable %s', CONF_HOST) + return False + + # import logging + # logging.getLogger('transmissionrpc').setLevel(logging.DEBUG) + + transmission_api = transmissionrpc.Client(host, port=port, user=username, password=password) + try: + session = transmission_api.session_stats() + print(transmission_api.session) + except TransmissionError: + _LOGGER.exception("Connection to Transmission API failed.") + return False + + # pylint: disable=global-statement + global _THROTTLED_REFRESH + _THROTTLED_REFRESH = Throttle(timedelta(seconds=1))(transmission_api.session_stats) + + dev = [] + for variable in config['monitored_variables']: + if variable['type'] not in SENSOR_TYPES: + _LOGGER.error('Sensor type: "%s" does not exist', variable['type']) + else: + dev.append(TransmissionSensor(variable['type'], transmission_api, name)) + + add_devices(dev) + + +class TransmissionSensor(Entity): + """ A Transmission sensor """ + + def __init__(self, sensor_type, transmission_client, client_name): + self._name = SENSOR_TYPES[sensor_type][0] + self.transmission_client = transmission_client + self.type = sensor_type + self.client_name = client_name + self._state = None + self._unit_of_measurement = SENSOR_TYPES[sensor_type][1] + + @property + def name(self): + return self.client_name + ' ' + self._name + + @property + def state(self): + """ Returns the state of the device. """ + return self._state + + @property + def unit_of_measurement(self): + """ Unit of measurement of this entity, if any. """ + return self._unit_of_measurement + + def refresh_transmission_data(self): + """ Calls the throttled Transmission refresh method. """ + if _THROTTLED_REFRESH is not None: + try: + _THROTTLED_REFRESH() + except TransmissionError: + _LOGGER.exception( + self.name + " Connection to Transmission API failed." + ) + + def update(self): + """ Gets the latest from Transmission and updates the state. """ + self.refresh_transmission_data() + if self.type == 'current_status': + if self.transmission_client.session: + upload = self.transmission_client.session.uploadSpeed + download = self.transmission_client.session.downloadSpeed + if upload > 0 and download > 0: + self._state = 'Up/Down' + elif upload > 0 and download == 0: + self._state = 'Seeding' + elif upload == 0 and download > 0: + self._state = 'Downloading' + else: + self._state = 'Idle' + else: + self._state = 'Unknown' + + if self.transmission_client.session: + if self.type == 'download_speed': + mb_spd = float(self.transmission_client.session.downloadSpeed) / 1024 / 1024 + self._state = round(mb_spd, 2 if mb_spd < 0.1 else 1) + elif self.type == 'upload_speed': + mb_spd = float(self.transmission_client.session.uploadSpeed) / 1024 / 1024 + self._state = round(mb_spd, 2 if mb_spd < 0.1 else 1) diff --git a/requirements.txt b/requirements.txt index 9f0352ccef1..8ceecf58908 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,8 +34,11 @@ python-nest>=2.1 # z-wave pydispatcher>=2.0.5 -# sensor.systemmonitor +# sensor.systemmonitor psutil>=2.2.1 -#pushover notifications -python-pushover>=0.2 \ No newline at end of file +# pushover notifications +python-pushover>=0.2 + +# Transmission Torrent Client +transmissionrpc>=0.11 \ No newline at end of file From e63d0d7aacf0f26dc0642732e97ec9f118c8f8e9 Mon Sep 17 00:00:00 2001 From: jamespcole Date: Tue, 7 Apr 2015 23:21:41 +1000 Subject: [PATCH 2/3] Tidied up the documentations and linting warnings --- .../components/sensor/transmission.py | 82 +++++++++++-------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/homeassistant/components/sensor/transmission.py b/homeassistant/components/sensor/transmission.py index 5738e791596..7b1a66315d1 100644 --- a/homeassistant/components/sensor/transmission.py +++ b/homeassistant/components/sensor/transmission.py @@ -1,39 +1,49 @@ """ -homeassistant.components.sensor.sabnzbd +homeassistant.components.sensor.transmission ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Monitors SABnzbd NZB client API +Monitors Transmission BitTorrent client API Configuration: -To use the SABnzbd sensor you will need to add something like the following to -your config/configuration.yaml +To use the Transmission sensor you will need to add something like the +following to your config/configuration.yaml sensor: - platform: sabnzbd - name: SAB - api_key: YOUR_API_KEY - base_url: YOUR_SABNZBD_BASE_URL + platform: transmission + name: Transmission + host: 192.168.1.26 + port: 9091 + username: YOUR_USERNAME + password: YOUR_PASSWORD monitored_variables: - type: 'current_status' - - type: 'speed' - - type: 'queue_size' - - type: 'queue_remaining' - - type: 'disk_size' - - type: 'disk_free' + - type: 'download_speed' + - type: 'upload_speed' VARIABLES: -base_url +host *Required -This is the base URL of your SABnzbd instance including the port number if not -running on 80 -Example: http://192.168.1.32:8124/ +This is the IP address of your Transmission Daemon +Example: 192.168.1.32 +port +*Optional +The port your Transmission daemon uses, defaults to 9091 +Example: 8080 + +username +*Required +Your Transmission username + +password +*Required +Your Transmission password name *Optional -The name to use when displaying this SABnzbd instance +The name to use when displaying this Transmission instance monitored_variables *Required @@ -64,11 +74,7 @@ import logging SENSOR_TYPES = { 'current_status': ['Status', ''], 'download_speed': ['Down Speed', 'MB/s'], - 'upload_speed': ['Up Speed', 'MB/s'], - 'queue_size': ['Queue', 'MB'], - 'queue_remaining': ['Left', 'MB'], - 'disk_size': ['Disk', 'GB'], - 'disk_free': ['Disk Free', 'GB'], + 'upload_speed': ['Up Speed', 'MB/s'] } _LOGGER = logging.getLogger(__name__) @@ -82,7 +88,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): host = config.get(CONF_HOST) username = config.get(CONF_USERNAME, None) password = config.get(CONF_PASSWORD, None) - port = config.get('port') + port = config.get('port', 9091) name = config.get("name", "Transmission") if not host: @@ -92,24 +98,26 @@ def setup_platform(hass, config, add_devices, discovery_info=None): # import logging # logging.getLogger('transmissionrpc').setLevel(logging.DEBUG) - transmission_api = transmissionrpc.Client(host, port=port, user=username, password=password) + transmission_api = transmissionrpc.Client( + host, port=port, user=username, password=password) try: - session = transmission_api.session_stats() - print(transmission_api.session) + transmission_api.session_stats() except TransmissionError: _LOGGER.exception("Connection to Transmission API failed.") return False # pylint: disable=global-statement global _THROTTLED_REFRESH - _THROTTLED_REFRESH = Throttle(timedelta(seconds=1))(transmission_api.session_stats) + _THROTTLED_REFRESH = Throttle(timedelta(seconds=1))( + transmission_api.session_stats) dev = [] for variable in config['monitored_variables']: if variable['type'] not in SENSOR_TYPES: _LOGGER.error('Sensor type: "%s" does not exist', variable['type']) else: - dev.append(TransmissionSensor(variable['type'], transmission_api, name)) + dev.append(TransmissionSensor( + variable['type'], transmission_api, name)) add_devices(dev) @@ -157,20 +165,22 @@ class TransmissionSensor(Entity): upload = self.transmission_client.session.uploadSpeed download = self.transmission_client.session.downloadSpeed if upload > 0 and download > 0: - self._state = 'Up/Down' + self._state = 'Up/Down' elif upload > 0 and download == 0: - self._state = 'Seeding' + self._state = 'Seeding' elif upload == 0 and download > 0: - self._state = 'Downloading' + self._state = 'Downloading' else: - self._state = 'Idle' + self._state = 'Idle' else: - self._state = 'Unknown' + self._state = 'Unknown' if self.transmission_client.session: if self.type == 'download_speed': - mb_spd = float(self.transmission_client.session.downloadSpeed) / 1024 / 1024 + mb_spd = float(self.transmission_client.session.downloadSpeed) + mb_spd = mb_spd / 1024 / 1024 self._state = round(mb_spd, 2 if mb_spd < 0.1 else 1) elif self.type == 'upload_speed': - mb_spd = float(self.transmission_client.session.uploadSpeed) / 1024 / 1024 + mb_spd = float(self.transmission_client.session.uploadSpeed) + mb_spd = mb_spd / 1024 / 1024 self._state = round(mb_spd, 2 if mb_spd < 0.1 else 1) From 439b7be77d3b048a65298e5347b3756ccf8fa49b Mon Sep 17 00:00:00 2001 From: jamespcole Date: Wed, 8 Apr 2015 00:35:57 +1000 Subject: [PATCH 3/3] Added the new transmission sensor to the coveragerc file --- .coveragerc | 1 + 1 file changed, 1 insertion(+) diff --git a/.coveragerc b/.coveragerc index f41886aaa0f..cc639df0c44 100644 --- a/.coveragerc +++ b/.coveragerc @@ -28,6 +28,7 @@ omit = homeassistant/components/device_tracker/netgear.py homeassistant/components/device_tracker/nmap_tracker.py homeassistant/components/device_tracker/ddwrt.py + homeassistant/components/sensor/transmission.py [report]