From 5122a499f3f44541b0e0c877f39e7aab3c30d798 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sat, 21 Apr 2018 19:59:27 +0200 Subject: [PATCH 1/3] Template Sensor Device Class Support --- homeassistant/components/sensor/template.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/template.py b/homeassistant/components/sensor/template.py index 1cd43262513381..3ab63536a87eff 100644 --- a/homeassistant/components/sensor/template.py +++ b/homeassistant/components/sensor/template.py @@ -6,16 +6,18 @@ """ import asyncio import logging +from typing import Optional import voluptuous as vol from homeassistant.core import callback -from homeassistant.components.sensor import ENTITY_ID_FORMAT, PLATFORM_SCHEMA +from homeassistant.components.sensor import ENTITY_ID_FORMAT, PLATFORM_SCHEMA, \ + DEVICE_CLASSES_SCHEMA from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, CONF_VALUE_TEMPLATE, CONF_ICON_TEMPLATE, CONF_ENTITY_PICTURE_TEMPLATE, ATTR_ENTITY_ID, CONF_SENSORS, EVENT_HOMEASSISTANT_START, CONF_FRIENDLY_NAME_TEMPLATE, - MATCH_ALL) + MATCH_ALL, CONF_DEVICE_CLASS) from homeassistant.exceptions import TemplateError import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity, async_generate_entity_id @@ -30,6 +32,7 @@ vol.Optional(CONF_FRIENDLY_NAME_TEMPLATE): cv.template, vol.Optional(ATTR_FRIENDLY_NAME): cv.string, vol.Optional(ATTR_UNIT_OF_MEASUREMENT): cv.string, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, vol.Optional(ATTR_ENTITY_ID): cv.entity_ids }) @@ -52,6 +55,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) friendly_name_template = device_config.get(CONF_FRIENDLY_NAME_TEMPLATE) unit_of_measurement = device_config.get(ATTR_UNIT_OF_MEASUREMENT) + device_class = device_config.get(CONF_DEVICE_CLASS) entity_ids = set() manual_entity_ids = device_config.get(ATTR_ENTITY_ID) @@ -86,7 +90,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): state_template, icon_template, entity_picture_template, - entity_ids) + entity_ids, + device_class) ) if not sensors: _LOGGER.error("No sensors added") @@ -101,7 +106,7 @@ class SensorTemplate(Entity): def __init__(self, hass, device_id, friendly_name, friendly_name_template, unit_of_measurement, state_template, icon_template, - entity_picture_template, entity_ids): + entity_picture_template, entity_ids, device_class): """Initialize the sensor.""" self.hass = hass self.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, device_id, @@ -116,6 +121,7 @@ def __init__(self, hass, device_id, friendly_name, friendly_name_template, self._icon = None self._entity_picture = None self._entities = entity_ids + self._device_class = device_class @asyncio.coroutine def async_added_to_hass(self): @@ -151,6 +157,11 @@ def icon(self): """Return the icon to use in the frontend, if any.""" return self._icon + @property + def device_class(self) -> Optional[str]: + """Return the device class of the sensor.""" + return self._device_class + @property def entity_picture(self): """Return the entity_picture to use in the frontend, if any.""" From 6416152a86b4fa1a858a5bfc9c3c2aacc76440de Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sat, 21 Apr 2018 20:16:15 +0200 Subject: [PATCH 2/3] Lint --- homeassistant/components/sensor/template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/sensor/template.py b/homeassistant/components/sensor/template.py index 3ab63536a87eff..65f49998dbf9fa 100644 --- a/homeassistant/components/sensor/template.py +++ b/homeassistant/components/sensor/template.py @@ -11,8 +11,8 @@ import voluptuous as vol from homeassistant.core import callback -from homeassistant.components.sensor import ENTITY_ID_FORMAT, PLATFORM_SCHEMA, \ - DEVICE_CLASSES_SCHEMA +from homeassistant.components.sensor import ENTITY_ID_FORMAT, \ + PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, CONF_VALUE_TEMPLATE, CONF_ICON_TEMPLATE, CONF_ENTITY_PICTURE_TEMPLATE, ATTR_ENTITY_ID, From a04a99bd9521f233da1dbf3815a2b90c667010e7 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sun, 22 Apr 2018 21:35:51 +0200 Subject: [PATCH 3/3] Add tests --- tests/components/sensor/test_template.py | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/components/sensor/test_template.py b/tests/components/sensor/test_template.py index b05fc90bfe4290..f8d912f24ddc92 100644 --- a/tests/components/sensor/test_template.py +++ b/tests/components/sensor/test_template.py @@ -267,3 +267,40 @@ def test_missing_template_does_not_create(self): self.hass.block_till_done() assert self.hass.states.all() == [] + + def test_setup_invalid_device_class(self): + """"Test setup with invalid device_class.""" + with assert_setup_component(0): + assert setup_component(self.hass, 'sensor', { + 'sensor': { + 'platform': 'template', + 'sensors': { + 'test': { + 'value_template': '{{ foo }}', + 'device_class': 'foobarnotreal', + }, + }, + } + }) + + def test_setup_valid_device_class(self): + """"Test setup with valid device_class.""" + with assert_setup_component(1): + assert setup_component(self.hass, 'sensor', { + 'sensor': { + 'platform': 'template', + 'sensors': { + 'test1': { + 'value_template': '{{ foo }}', + 'device_class': 'temperature', + }, + 'test2': {'value_template': '{{ foo }}'}, + } + } + }) + self.hass.block_till_done() + + state = self.hass.states.get('sensor.test1') + assert state.attributes['device_class'] == 'temperature' + state = self.hass.states.get('sensor.test2') + assert 'device_class' not in state.attributes