From 214a18f08cc45e46660f0e049ac3ee9302066394 Mon Sep 17 00:00:00 2001 From: Erik Eriksson <molobrakos@users.noreply.github.com> Date: Thu, 3 Nov 2016 05:20:21 +0100 Subject: [PATCH] Support for Dovado routers (#4176) * Implemented support for the Dovado router * Update .coveragerc --- .coveragerc | 1 + homeassistant/components/sensor/dovado.py | 174 ++++++++++++++++++++++ requirements_all.txt | 3 + 3 files changed, 178 insertions(+) create mode 100644 homeassistant/components/sensor/dovado.py diff --git a/.coveragerc b/.coveragerc index 294b6b1b747..d1ead447856 100644 --- a/.coveragerc +++ b/.coveragerc @@ -244,6 +244,7 @@ omit = homeassistant/components/sensor/darksky.py homeassistant/components/sensor/deutsche_bahn.py homeassistant/components/sensor/dht.py + homeassistant/components/sensor/dovado.py homeassistant/components/sensor/dte_energy_bridge.py homeassistant/components/sensor/efergy.py homeassistant/components/sensor/eliqonline.py diff --git a/homeassistant/components/sensor/dovado.py b/homeassistant/components/sensor/dovado.py new file mode 100644 index 00000000000..1e1bf785760 --- /dev/null +++ b/homeassistant/components/sensor/dovado.py @@ -0,0 +1,174 @@ +""" +Support for Dovado router. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.dovado/ +""" +import logging +import re +from datetime import timedelta + +import voluptuous as vol + +from homeassistant.helpers.entity import Entity +from homeassistant.util import Throttle +from homeassistant.util import slugify +import homeassistant.helpers.config_validation as cv +from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, + CONF_HOST, CONF_PORT, + CONF_SENSORS, STATE_UNKNOWN) +from homeassistant.components.sensor import (DOMAIN, PLATFORM_SCHEMA) + +_LOGGER = logging.getLogger(__name__) + +REQUIREMENTS = ['dovado==0.1.15'] + +MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30) + +SENSOR_UPLOAD = "upload" +SENSOR_DOWNLOAD = "download" +SENSOR_SIGNAL = "signal" +SENSOR_NETWORK = "network" +SENSOR_SMS_UNREAD = "sms" + +SENSORS = { + SENSOR_NETWORK: ("signal strength", "Network", None, + "mdi:access-point-network"), + SENSOR_SIGNAL: ("signal strength", "Signal Strength", "%", + "mdi:signal"), + SENSOR_SMS_UNREAD: ("sms unread", "SMS unread", "", + "mdi:message-text-outline"), + SENSOR_UPLOAD: ("traffic modem tx", "Sent", "GiB", + "mdi:cloud-upload"), + SENSOR_DOWNLOAD: ("traffic modem rx", "Received", "GiB", + "mdi:cloud-download"), +} + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_USERNAME): cv.string, + vol.Required(CONF_PASSWORD): cv.string, + vol.Optional(CONF_HOST): cv.string, + vol.Optional(CONF_PORT): cv.port, + vol.Optional(CONF_SENSORS): + vol.All(cv.ensure_list, [vol.In(SENSORS)]), +}) + + +def setup_platform(hass, config, add_devices, discovery_info=None): + """Setup the dovado platform for sensors.""" + return Dovado().setup(hass, config, add_devices) + + +class Dovado: + """A connection to the router.""" + + def __init__(self): + """Initialize.""" + self.state = {} + self._dovado = None + + def setup(self, hass, config, add_devices): + """Setup the connection.""" + import dovado + self._dovado = dovado.Dovado( + config.get(CONF_USERNAME), + config.get(CONF_PASSWORD), + config.get(CONF_HOST), + config.get(CONF_PORT)) + + if not self.update(): + return False + + def send_sms(service): + """Send SMS through the router.""" + number = service.data.get("number"), + message = service.data.get("message") + _LOGGER.debug("message for %s: %s", + number, message) + self._dovado.send_sms(number, message) + + if self.state["sms"] == "enabled": + service_name = slugify("{} {}".format(self.name, + "send_sms")) + hass.services.register(DOMAIN, service_name, send_sms) + + for sensor in SENSORS: + if sensor in config.get(CONF_SENSORS, [sensor]): + add_devices([DovadoSensor(self, sensor)]) + + return True + + @property + def name(self): + """Name of the router.""" + return self.state["product name"] + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Update device state.""" + _LOGGER.info("Updating") + try: + self.state = self._dovado.query_state() + self.state.update( + connected=self.state["modem status"] == "CONNECTED") + _LOGGER.debug("Received: %s", self.state) + return True + except OSError as error: + _LOGGER.error("Could not contact the router: %s", error) + return False + + +class DovadoSensor(Entity): + """Representation of a Dovado sensor.""" + + def __init__(self, dovado, sensor): + """Initialize the sensor.""" + self._dovado = dovado + self._sensor = sensor + + def update(self): + """Update sensor values.""" + self._dovado.update() + + @property + def name(self): + """Return the name of the sensor.""" + return "{} {}".format(self._dovado.name, + SENSORS[self._sensor][1]) + + @property + def state(self): + """Return the sensor state.""" + key = SENSORS[self._sensor][0] + result = self._dovado.state[key] + if self._sensor == SENSOR_NETWORK: + match = re.search(r"\((.+)\)", result) + return match.group(1) if match else STATE_UNKNOWN + elif self._sensor == SENSOR_SIGNAL: + try: + return int(result.split()[0]) + except ValueError: + return 0 + elif self._sensor == SENSOR_SMS_UNREAD: + return int(result) + elif self._sensor in [SENSOR_UPLOAD, SENSOR_DOWNLOAD]: + gib = pow(2, 30) + return round(int(result) / gib, 1) + else: + return result + + @property + def icon(self): + """Return the icon for the sensor.""" + return SENSORS[self._sensor][3] + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return SENSORS[self._sensor][2] + + @property + def device_state_attributes(self): + """Return the state attributes.""" + return {k: v for k, v in self._dovado.state.items() + if k not in ["date", "time"]} diff --git a/requirements_all.txt b/requirements_all.txt index 121597b9be9..6b02b09d95c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -78,6 +78,9 @@ distro==1.0.0 # homeassistant.components.notify.xmpp dnspython3==1.15.0 +# homeassistant.components.sensor.dovado +dovado==0.1.15 + # homeassistant.components.dweet # homeassistant.components.sensor.dweet dweepy==0.2.0 -- GitLab