From 03d6a7c42a518eba5008d6bccc8ee833b938751e Mon Sep 17 00:00:00 2001 From: gwendalg Date: Tue, 4 Oct 2016 21:57:40 -0700 Subject: [PATCH] Add Ted5000 Sensor (#3559) * Add Ted5000 Sensor Signed-off-by: Gwendal Grignou * sensors: ted5000: use requests instead of urllib. Signed-off-by: Gwendal Grignou * Update ted5000.py Add timeout to requests call. --- .coveragerc | 1 + homeassistant/components/sensor/ted5000.py | 124 +++++++++++++++++++++ requirements_all.txt | 1 + 3 files changed, 126 insertions(+) create mode 100644 homeassistant/components/sensor/ted5000.py diff --git a/.coveragerc b/.coveragerc index 5cedb8c5c48..c58938cf866 100644 --- a/.coveragerc +++ b/.coveragerc @@ -262,6 +262,7 @@ omit = homeassistant/components/sensor/swiss_hydrological_data.py homeassistant/components/sensor/swiss_public_transport.py homeassistant/components/sensor/systemmonitor.py + homeassistant/components/sensor/ted5000.py homeassistant/components/sensor/temper.py homeassistant/components/sensor/time_date.py homeassistant/components/sensor/torque.py diff --git a/homeassistant/components/sensor/ted5000.py b/homeassistant/components/sensor/ted5000.py new file mode 100644 index 00000000000..f995b9232aa --- /dev/null +++ b/homeassistant/components/sensor/ted5000.py @@ -0,0 +1,124 @@ +""" +Support gahtering ted500 information. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.ted5000/ + +Ted5000 collection from +https://github.com/weirded/ted5000-collectd-plugin/blob/master/ted5000.py + +Ted500 framework from glances plugin. +""" +import logging +from datetime import timedelta +import requests +import voluptuous as vol + +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import (CONF_HOST, CONF_NAME, CONF_PORT) +from homeassistant.helpers import config_validation as cv +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle + +_LOGGER = logging.getLogger(__name__) + +REQUIREMENTS = ['xmltodict==0.10.2'] + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_PORT, default=80): cv.port, + vol.Optional(CONF_NAME, default='ted'): cv.string, +}) + +_LOGGER = logging.getLogger(__name__) +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=10) + + +# pylint: disable=unused-variable +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the Ted5000 sensor.""" + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + url = "http://{}:{}/api/LiveData.xml".format(host, port) + + gateway = Ted5000Gateway(url) + + # Get MUT information to create the sensors. + gateway.update() + + dev = [] + for mtu in gateway.data: + dev.append(Ted5000Sensor(gateway, config.get('name'), mtu, 'W')) + dev.append(Ted5000Sensor(gateway, config.get('name'), mtu, 'V')) + + add_devices(dev) + return True + + +class Ted5000Sensor(Entity): + """Implementation of a Ted5000 sensor.""" + + def __init__(self, gateway, name, mtu, unit): + """Initialize the sensor.""" + units = {'W': 'power', 'V': 'voltage'} + self._gateway = gateway + self._name = '%s mtu%d %s' % (name, mtu, units[unit]) + self._mtu = mtu + self._unit = unit + self.update() + + @property + def name(self): + """The name of the sensor.""" + return self._name + + @property + def unit_of_measurement(self): + """Return the unit the value is expressed in.""" + return self._unit + + @property + def state(self): + """Return the state of the resources.""" + try: + return self._gateway.data[self._mtu][self._unit] + except KeyError: + pass + + def update(self): + """Get the latest data from REST API.""" + self._gateway.update() + + +# pylint: disable=too-few-public-methods +class Ted5000Gateway(object): + """The class for handling the data retrieval.""" + + def __init__(self, url): + """Initialize the data object.""" + self.url = url + self.data = dict() + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Get the latest data from the Ted5000 XML API.""" + import xmltodict + try: + request = requests.get(self.url, timeout=10) + except requests.exceptions.RequestException as err: + _LOGGER.error("No connection to endpoint: %s", err) + else: + doc = xmltodict.parse(request.text) + mtus = int(doc["LiveData"]["System"]["NumberMTU"]) + + for mtu in range(1, mtus + 1): + power = int(doc["LiveData"]["Power"]["MTU%d" % mtu] + ["PowerNow"]) + voltage = int(doc["LiveData"]["Voltage"]["MTU%d" % mtu] + ["VoltageNow"]) + + if power == 0 or voltage == 0: + continue + else: + self.data[mtu] = {'W': power, + 'V': voltage / 10} diff --git a/requirements_all.txt b/requirements_all.txt index 9d582173349..d952400bbba 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -515,6 +515,7 @@ xbee-helper==0.0.7 xboxapi==0.1.1 # homeassistant.components.sensor.swiss_hydrological_data +# homeassistant.components.sensor.ted5000 # homeassistant.components.sensor.yr xmltodict==0.10.2