Add template support to rest sensor

This commit is contained in:
Philip Lundrigan 2015-12-11 15:19:49 -07:00
parent 13b0d2afa3
commit 1c54111018

View File

@ -7,12 +7,12 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.rest/ https://home-assistant.io/components/sensor.rest/
""" """
from datetime import timedelta from datetime import timedelta
from json import loads
import logging import logging
import requests import requests
import jinja2.exceptions
from homeassistant.util import Throttle from homeassistant.const import CONF_VALUE_TEMPLATE
from homeassistant.util import template, Throttle
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -59,17 +59,16 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
'Please check the URL in the configuration file.') 'Please check the URL in the configuration file.')
return False return False
value_template = config.get(CONF_VALUE_TEMPLATE)
data = response.text
if value_template is not None:
try: try:
data = loads(response.text) template.render_with_possible_json_value(hass,
except ValueError: value_template,
_LOGGER.error('No valid JSON in the response in: %s', data) data)
return False except jinja2.exceptions.UndefinedError:
_LOGGER.error('Template "%s" not found in response: "%s"',
try: value_template, data)
RestSensor.extract_value(data, config.get('variable'))
except KeyError:
_LOGGER.error('Variable "%s" not found in response: "%s"',
config.get('variable'), data)
return False return False
if use_get: if use_get:
@ -77,39 +76,26 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
elif use_post: elif use_post:
rest = RestDataPost(resource, payload, verify_ssl) rest = RestDataPost(resource, payload, verify_ssl)
add_devices([RestSensor(rest, add_devices([RestSensor(hass,
rest,
config.get('name', DEFAULT_NAME), config.get('name', DEFAULT_NAME),
config.get('variable'),
config.get('unit_of_measurement'), config.get('unit_of_measurement'),
config.get('correction_factor', None), config.get(CONF_VALUE_TEMPLATE))])
config.get('decimal_places', None))])
# pylint: disable=too-many-arguments # pylint: disable=too-many-arguments
class RestSensor(Entity): class RestSensor(Entity):
""" Implements a REST sensor. """ """ Implements a REST sensor. """
def __init__(self, rest, name, variable, unit_of_measurement, corr_factor, def __init__(self, hass, rest, name, unit_of_measurement, value_template):
decimal_places): self._hass = hass
self.rest = rest self.rest = rest
self._name = name self._name = name
self._variable = variable
self._state = 'n/a' self._state = 'n/a'
self._unit_of_measurement = unit_of_measurement self._unit_of_measurement = unit_of_measurement
self._corr_factor = corr_factor self._value_template = value_template
self._decimal_places = decimal_places
self.update() self.update()
@classmethod
def extract_value(cls, data, variable):
""" Extracts the value using a key name or a path. """
if isinstance(variable, list):
for variable_item in variable:
data = data[variable_item]
return data
else:
return data[variable]
@property @property
def name(self): def name(self):
""" The name of the sensor. """ """ The name of the sensor. """
@ -133,18 +119,10 @@ class RestSensor(Entity):
if 'error' in value: if 'error' in value:
self._state = value['error'] self._state = value['error']
else: else:
try: if self._value_template is not None:
if value is not None: value = template.render_with_possible_json_value(
value = RestSensor.extract_value(value, self._variable) self._hass, self._value_template, value)
if self._corr_factor is not None:
value = float(value) * float(self._corr_factor)
if self._decimal_places is not None:
value = round(value, self._decimal_places)
if self._decimal_places == 0:
value = int(value)
self._state = value self._state = value
except ValueError:
self._state = RestSensor.extract_value(value, self._variable)
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
@ -164,7 +142,7 @@ class RestDataGet(object):
verify=self._verify_ssl) verify=self._verify_ssl)
if 'error' in self.data: if 'error' in self.data:
del self.data['error'] del self.data['error']
self.data = response.json() self.data = response.text
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
_LOGGER.error("No route to resource/endpoint.") _LOGGER.error("No route to resource/endpoint.")
self.data['error'] = 'N/A' self.data['error'] = 'N/A'
@ -188,7 +166,7 @@ class RestDataPost(object):
timeout=10, verify=self._verify_ssl) timeout=10, verify=self._verify_ssl)
if 'error' in self.data: if 'error' in self.data:
del self.data['error'] del self.data['error']
self.data = response.json() self.data = response.text
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
_LOGGER.error("No route to resource/endpoint.") _LOGGER.error("No route to resource/endpoint.")
self.data['error'] = 'N/A' self.data['error'] = 'N/A'