From 555184a4b729852584d72273790e06eb131f8c76 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Wed, 15 Aug 2018 07:49:34 +0200 Subject: [PATCH] Update Glances sensor (#15981) * Refactor Glances sensor * Add glances_api to requirements_all.txt * Add support for version as configuration option --- homeassistant/components/sensor/glances.py | 71 ++++++++++++++-------- requirements_all.txt | 3 + 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/homeassistant/components/sensor/glances.py b/homeassistant/components/sensor/glances.py index a6dfd89e45a..c2a6607334d 100644 --- a/homeassistant/components/sensor/glances.py +++ b/homeassistant/components/sensor/glances.py @@ -4,25 +4,30 @@ Support gathering system information of hosts which are running glances. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.glances/ """ -import logging from datetime import timedelta +import logging -import requests import voluptuous as vol -import homeassistant.helpers.config_validation as cv from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import ( - CONF_HOST, CONF_PORT, CONF_NAME, CONF_RESOURCES, TEMP_CELSIUS) + CONF_HOST, CONF_NAME, CONF_PORT, CONF_RESOURCES, TEMP_CELSIUS) +from homeassistant.exceptions import PlatformNotReady +from homeassistant.helpers.aiohttp_client import async_get_clientsession +import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle +REQUIREMENTS = ['glances_api==0.1.0'] + _LOGGER = logging.getLogger(__name__) -_RESOURCE = 'api/2/all' + +CONF_VERSION = 'version' DEFAULT_HOST = 'localhost' DEFAULT_NAME = 'Glances' DEFAULT_PORT = '61208' +DEFAULT_VERSION = 2 MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1) @@ -53,33 +58,43 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Optional(CONF_RESOURCES, default=['disk_use']): vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), + vol.Optional(CONF_VERSION, default=DEFAULT_VERSION): vol.In([2, 3]), }) -def setup_platform(hass, config, add_devices, discovery_info=None): - """Set up the Glances sensor.""" +async def async_setup_platform( + hass, config, async_add_devices, discovery_info=None): + """Set up the Glances sensors.""" + from glances_api import Glances + name = config.get(CONF_NAME) host = config.get(CONF_HOST) port = config.get(CONF_PORT) - url = 'http://{}:{}/{}'.format(host, port, _RESOURCE) + version = config.get(CONF_VERSION) var_conf = config.get(CONF_RESOURCES) - rest = GlancesData(url) - rest.update() + session = async_get_clientsession(hass) + glances = GlancesData( + Glances(hass.loop, session, host=host, port=port, version=version)) + + await glances.async_update() + + if glances.api.data is None: + raise PlatformNotReady dev = [] for resource in var_conf: - dev.append(GlancesSensor(rest, name, resource)) + dev.append(GlancesSensor(glances, name, resource)) - add_devices(dev, True) + async_add_devices(dev, True) class GlancesSensor(Entity): """Implementation of a Glances sensor.""" - def __init__(self, rest, name, sensor_type): + def __init__(self, glances, name, sensor_type): """Initialize the sensor.""" - self.rest = rest + self.glances = glances self._name = name self.type = sensor_type self._state = None @@ -103,17 +118,17 @@ class GlancesSensor(Entity): @property def available(self): """Could the device be accessed during the last update call.""" - return self.rest.data is not None + return self.glances.available @property def state(self): """Return the state of the resources.""" return self._state - def update(self): + async def async_update(self): """Get the latest data from REST API.""" - self.rest.update() - value = self.rest.data + await self.glances.async_update() + value = self.glances.api.data if value is not None: if self.type == 'disk_use_percent': @@ -179,17 +194,19 @@ class GlancesSensor(Entity): class GlancesData: """The class for handling the data retrieval.""" - def __init__(self, resource): + def __init__(self, api): """Initialize the data object.""" - self._resource = resource - self.data = {} + self.api = api + self.available = True @Throttle(MIN_TIME_BETWEEN_UPDATES) - def update(self): + async def async_update(self): """Get the latest data from the Glances REST API.""" + from glances_api.exceptions import GlancesApiError + try: - response = requests.get(self._resource, timeout=10) - self.data = response.json() - except requests.exceptions.ConnectionError: - _LOGGER.error("Connection error: %s", self._resource) - self.data = None + await self.api.get_data() + self.available = True + except GlancesApiError: + _LOGGER.error("Unable to fetch data from Glances") + self.available = False diff --git a/requirements_all.txt b/requirements_all.txt index 4736e4e4c6d..e9de6c91a72 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -386,6 +386,9 @@ gearbest_parser==1.0.7 # homeassistant.components.sensor.gitter gitterpy==0.1.7 +# homeassistant.components.sensor.glances +glances_api==0.1.0 + # homeassistant.components.notify.gntp gntp==1.0.3