diff --git a/homeassistant/components/binary_sensor/__init__.py b/homeassistant/components/binary_sensor/__init__.py index 26a19ce3f59..ab49c13770a 100644 --- a/homeassistant/components/binary_sensor/__init__.py +++ b/homeassistant/components/binary_sensor/__init__.py @@ -14,13 +14,13 @@ from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.entity import Entity from homeassistant.const import (STATE_ON, STATE_OFF) from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa +from homeassistant.helpers.deprecation import deprecated_substitute DOMAIN = 'binary_sensor' SCAN_INTERVAL = timedelta(seconds=30) ENTITY_ID_FORMAT = DOMAIN + '.{}' -SENSOR_CLASSES = [ - None, # Generic on/off +DEVICE_CLASSES = [ 'cold', # On means cold (or too cold) 'connectivity', # On means connection present, Off = no connection 'gas', # CO, CO2, etc. @@ -38,7 +38,7 @@ SENSOR_CLASSES = [ 'vibration', # On means vibration detected, Off means no vibration ] -SENSOR_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(SENSOR_CLASSES)) +DEVICE_CLASSES_SCHEMA = vol.All(vol.Lower, vol.In(DEVICE_CLASSES)) @asyncio.coroutine @@ -66,16 +66,7 @@ class BinarySensorDevice(Entity): return STATE_ON if self.is_on else STATE_OFF @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + @deprecated_substitute('sensor_class') + def device_class(self): + """Return the class of this device, from component DEVICE_CLASSES.""" return None - - @property - def state_attributes(self): - """Return device specific state attributes.""" - attr = {} - - if self.sensor_class is not None: - attr['sensor_class'] = self.sensor_class - - return attr diff --git a/homeassistant/components/binary_sensor/arest.py b/homeassistant/components/binary_sensor/arest.py index 834fb490049..efa6043a035 100644 --- a/homeassistant/components/binary_sensor/arest.py +++ b/homeassistant/components/binary_sensor/arest.py @@ -11,11 +11,12 @@ import requests import voluptuous as vol from homeassistant.components.binary_sensor import ( - BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA) + BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA) from homeassistant.const import ( - CONF_RESOURCE, CONF_PIN, CONF_NAME, CONF_SENSOR_CLASS) + CONF_RESOURCE, CONF_PIN, CONF_NAME, CONF_SENSOR_CLASS, CONF_DEVICE_CLASS) from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.deprecation import get_deprecated _LOGGER = logging.getLogger(__name__) @@ -25,7 +26,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_RESOURCE): cv.url, vol.Optional(CONF_NAME): cv.string, vol.Required(CONF_PIN): cv.string, - vol.Optional(CONF_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA, + vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, }) @@ -33,7 +35,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the aREST binary sensor.""" resource = config.get(CONF_RESOURCE) pin = config.get(CONF_PIN) - sensor_class = config.get(CONF_SENSOR_CLASS) + device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) try: response = requests.get(resource, timeout=10).json() @@ -49,18 +51,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None): add_devices([ArestBinarySensor( arest, resource, config.get(CONF_NAME, response[CONF_NAME]), - sensor_class, pin)]) + device_class, pin)]) class ArestBinarySensor(BinarySensorDevice): """Implement an aREST binary sensor for a pin.""" - def __init__(self, arest, resource, name, sensor_class, pin): + def __init__(self, arest, resource, name, device_class, pin): """Initialize the aREST device.""" self.arest = arest self._resource = resource self._name = name - self._sensor_class = sensor_class + self._device_class = device_class self._pin = pin self.update() @@ -81,9 +83,9 @@ class ArestBinarySensor(BinarySensorDevice): return bool(self.arest.data.get('state')) @property - def sensor_class(self): + def device_class(self): """Return the class of this sensor.""" - return self._sensor_class + return self._device_class def update(self): """Get the latest data from aREST API.""" diff --git a/homeassistant/components/binary_sensor/bloomsky.py b/homeassistant/components/binary_sensor/bloomsky.py index 2419d6f766e..845a58ee918 100644 --- a/homeassistant/components/binary_sensor/bloomsky.py +++ b/homeassistant/components/binary_sensor/bloomsky.py @@ -64,8 +64,8 @@ class BloomSkySensor(BinarySensorDevice): return self._unique_id @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return SENSOR_TYPES.get(self._sensor_name) @property diff --git a/homeassistant/components/binary_sensor/command_line.py b/homeassistant/components/binary_sensor/command_line.py index f051120d680..e08ebbe18f8 100644 --- a/homeassistant/components/binary_sensor/command_line.py +++ b/homeassistant/components/binary_sensor/command_line.py @@ -10,12 +10,13 @@ import logging import voluptuous as vol from homeassistant.components.binary_sensor import ( - BinarySensorDevice, SENSOR_CLASSES_SCHEMA, PLATFORM_SCHEMA) + BinarySensorDevice, DEVICE_CLASSES_SCHEMA, PLATFORM_SCHEMA) from homeassistant.components.sensor.command_line import CommandSensorData from homeassistant.const import ( CONF_PAYLOAD_OFF, CONF_PAYLOAD_ON, CONF_NAME, CONF_VALUE_TEMPLATE, - CONF_SENSOR_CLASS, CONF_COMMAND) + CONF_SENSOR_CLASS, CONF_COMMAND, CONF_DEVICE_CLASS) import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.deprecation import get_deprecated _LOGGER = logging.getLogger(__name__) @@ -30,7 +31,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string, vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string, - vol.Optional(CONF_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA, + vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, }) @@ -42,27 +44,27 @@ def setup_platform(hass, config, add_devices, discovery_info=None): command = config.get(CONF_COMMAND) payload_off = config.get(CONF_PAYLOAD_OFF) payload_on = config.get(CONF_PAYLOAD_ON) - sensor_class = config.get(CONF_SENSOR_CLASS) + device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass data = CommandSensorData(command) add_devices([CommandBinarySensor( - hass, data, name, sensor_class, payload_on, payload_off, + hass, data, name, device_class, payload_on, payload_off, value_template)]) class CommandBinarySensor(BinarySensorDevice): """Represent a command line binary sensor.""" - def __init__(self, hass, data, name, sensor_class, payload_on, + def __init__(self, hass, data, name, device_class, payload_on, payload_off, value_template): """Initialize the Command line binary sensor.""" self._hass = hass self.data = data self._name = name - self._sensor_class = sensor_class + self._device_class = device_class self._state = False self._payload_on = payload_on self._payload_off = payload_off @@ -80,9 +82,9 @@ class CommandBinarySensor(BinarySensorDevice): return self._state @ property - def sensor_class(self): + def device_class(self): """Return the class of the binary sensor.""" - return self._sensor_class + return self._device_class def update(self): """Get the latest data and updates the state.""" diff --git a/homeassistant/components/binary_sensor/concord232.py b/homeassistant/components/binary_sensor/concord232.py index 109eed1fdc2..38ec0a74f97 100755 --- a/homeassistant/components/binary_sensor/concord232.py +++ b/homeassistant/components/binary_sensor/concord232.py @@ -11,7 +11,7 @@ import requests import voluptuous as vol from homeassistant.components.binary_sensor import ( - BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES) + BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES) from homeassistant.const import (CONF_HOST, CONF_PORT) import homeassistant.helpers.config_validation as cv @@ -30,7 +30,7 @@ DEFAULT_SSL = False SCAN_INTERVAL = datetime.timedelta(seconds=1) ZONE_TYPES_SCHEMA = vol.Schema({ - cv.positive_int: vol.In(SENSOR_CLASSES), + cv.positive_int: vol.In(DEVICE_CLASSES), }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -102,8 +102,8 @@ class Concord232ZoneSensor(BinarySensorDevice): self.update() @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return self._zone_type @property diff --git a/homeassistant/components/binary_sensor/demo.py b/homeassistant/components/binary_sensor/demo.py index 6f7d59c65fd..9dbae2fdb49 100644 --- a/homeassistant/components/binary_sensor/demo.py +++ b/homeassistant/components/binary_sensor/demo.py @@ -18,14 +18,14 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class DemoBinarySensor(BinarySensorDevice): """A Demo binary sensor.""" - def __init__(self, name, state, sensor_class): + def __init__(self, name, state, device_class): """Initialize the demo sensor.""" self._name = name self._state = state - self._sensor_type = sensor_class + self._sensor_type = device_class @property - def sensor_class(self): + def device_class(self): """Return the class of this sensor.""" return self._sensor_type diff --git a/homeassistant/components/binary_sensor/digital_ocean.py b/homeassistant/components/binary_sensor/digital_ocean.py index 4c5783cc220..31f29597f06 100644 --- a/homeassistant/components/binary_sensor/digital_ocean.py +++ b/homeassistant/components/binary_sensor/digital_ocean.py @@ -63,7 +63,7 @@ class DigitalOceanBinarySensor(BinarySensorDevice): return self.data.status == 'active' @property - def sensor_class(self): + def device_class(self): """Return the class of this sensor.""" return DEFAULT_SENSOR_CLASS diff --git a/homeassistant/components/binary_sensor/ecobee.py b/homeassistant/components/binary_sensor/ecobee.py index 93583ff08b1..b2a5d21386b 100644 --- a/homeassistant/components/binary_sensor/ecobee.py +++ b/homeassistant/components/binary_sensor/ecobee.py @@ -38,7 +38,7 @@ class EcobeeBinarySensor(BinarySensorDevice): self.sensor_name = sensor_name self.index = sensor_index self._state = None - self._sensor_class = 'occupancy' + self._device_class = 'occupancy' self.update() @property @@ -57,9 +57,9 @@ class EcobeeBinarySensor(BinarySensorDevice): return "binary_sensor_ecobee_{}_{}".format(self._name, self.index) @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" - return self._sensor_class + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" + return self._device_class def update(self): """Get the latest state of the sensor.""" diff --git a/homeassistant/components/binary_sensor/enocean.py b/homeassistant/components/binary_sensor/enocean.py index bd68a232f22..c89148ebc15 100644 --- a/homeassistant/components/binary_sensor/enocean.py +++ b/homeassistant/components/binary_sensor/enocean.py @@ -9,10 +9,12 @@ import logging import voluptuous as vol from homeassistant.components.binary_sensor import ( - BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA) + BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA) from homeassistant.components import enocean -from homeassistant.const import (CONF_NAME, CONF_ID, CONF_SENSOR_CLASS) +from homeassistant.const import ( + CONF_NAME, CONF_ID, CONF_SENSOR_CLASS, CONF_DEVICE_CLASS) import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.deprecation import get_deprecated _LOGGER = logging.getLogger(__name__) @@ -22,7 +24,8 @@ DEFAULT_NAME = 'EnOcean binary sensor' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_ID): vol.All(cv.ensure_list, [vol.Coerce(int)]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA, + vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, }) @@ -30,15 +33,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the Binary Sensor platform fo EnOcean.""" dev_id = config.get(CONF_ID) devname = config.get(CONF_NAME) - sensor_class = config.get(CONF_SENSOR_CLASS) + device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) - add_devices([EnOceanBinarySensor(dev_id, devname, sensor_class)]) + add_devices([EnOceanBinarySensor(dev_id, devname, device_class)]) class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice): """Representation of EnOcean binary sensors such as wall switches.""" - def __init__(self, dev_id, devname, sensor_class): + def __init__(self, dev_id, devname, device_class): """Initialize the EnOcean binary sensor.""" enocean.EnOceanDevice.__init__(self) self.stype = "listener" @@ -46,7 +49,7 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice): self.which = -1 self.onoff = -1 self.devname = devname - self._sensor_class = sensor_class + self._device_class = device_class @property def name(self): @@ -54,9 +57,9 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice): return self.devname @property - def sensor_class(self): + def device_class(self): """Return the class of this sensor.""" - return self._sensor_class + return self._device_class def value_changed(self, value, value2): """Fire an event with the data that have changed. diff --git a/homeassistant/components/binary_sensor/envisalink.py b/homeassistant/components/binary_sensor/envisalink.py index 5bbc15aefcf..3e669333d69 100644 --- a/homeassistant/components/binary_sensor/envisalink.py +++ b/homeassistant/components/binary_sensor/envisalink.py @@ -60,8 +60,8 @@ class EnvisalinkBinarySensor(EnvisalinkDevice, BinarySensorDevice): return self._info['status']['open'] @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return self._zone_type def _update_callback(self, zone): diff --git a/homeassistant/components/binary_sensor/ffmpeg_motion.py b/homeassistant/components/binary_sensor/ffmpeg_motion.py index 70e13722b85..8c822c56361 100644 --- a/homeassistant/components/binary_sensor/ffmpeg_motion.py +++ b/homeassistant/components/binary_sensor/ffmpeg_motion.py @@ -122,6 +122,6 @@ class FFmpegMotion(FFmpegBinarySensor): ) @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return "motion" diff --git a/homeassistant/components/binary_sensor/ffmpeg_noise.py b/homeassistant/components/binary_sensor/ffmpeg_noise.py index b4592fceefd..8db4691d743 100644 --- a/homeassistant/components/binary_sensor/ffmpeg_noise.py +++ b/homeassistant/components/binary_sensor/ffmpeg_noise.py @@ -91,6 +91,6 @@ class FFmpegNoise(FFmpegBinarySensor): ) @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return "sound" diff --git a/homeassistant/components/binary_sensor/flic.py b/homeassistant/components/binary_sensor/flic.py index 94a75fcda4b..eedcfb6060e 100644 --- a/homeassistant/components/binary_sensor/flic.py +++ b/homeassistant/components/binary_sensor/flic.py @@ -179,12 +179,9 @@ class FlicButton(BinarySensorDevice): return False @property - def state_attributes(self): + def device_state_attributes(self): """Return device specific state attributes.""" - attr = super(FlicButton, self).state_attributes - attr["address"] = self.address - - return attr + return {"address": self.address} def _queued_event_check(self, click_type, time_diff): """Generate a log message and returns true if timeout exceeded.""" diff --git a/homeassistant/components/binary_sensor/hikvision.py b/homeassistant/components/binary_sensor/hikvision.py index 1cc98372cee..e14d4149ffe 100644 --- a/homeassistant/components/binary_sensor/hikvision.py +++ b/homeassistant/components/binary_sensor/hikvision.py @@ -29,7 +29,7 @@ DEFAULT_DELAY = 0 ATTR_DELAY = 'delay' -SENSOR_CLASS_MAP = { +DEVICE_CLASS_MAP = { 'Motion': 'motion', 'Line Crossing': 'motion', 'IO Trigger': None, @@ -201,10 +201,10 @@ class HikvisionBinarySensor(BinarySensorDevice): return self._sensor_state() @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" try: - return SENSOR_CLASS_MAP[self._sensor] + return DEVICE_CLASS_MAP[self._sensor] except KeyError: # Sensor must be unknown to us, add as generic return None diff --git a/homeassistant/components/binary_sensor/homematic.py b/homeassistant/components/binary_sensor/homematic.py index 82b77eb11d4..5379ccfe5d6 100644 --- a/homeassistant/components/binary_sensor/homematic.py +++ b/homeassistant/components/binary_sensor/homematic.py @@ -54,8 +54,8 @@ class HMBinarySensor(HMDevice, BinarySensorDevice): return bool(self._hm_get_state()) @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" if not self.available: return None diff --git a/homeassistant/components/binary_sensor/iss.py b/homeassistant/components/binary_sensor/iss.py index b4182557878..44d2b16fcc9 100644 --- a/homeassistant/components/binary_sensor/iss.py +++ b/homeassistant/components/binary_sensor/iss.py @@ -26,7 +26,7 @@ ATTR_ISS_NUMBER_PEOPLE_SPACE = 'number_of_people_in_space' CONF_SHOW_ON_MAP = 'show_on_map' DEFAULT_NAME = 'ISS' -DEFAULT_SENSOR_CLASS = 'visible' +DEFAULT_DEVICE_CLASS = 'visible' MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=60) @@ -77,9 +77,9 @@ class IssBinarySensor(BinarySensorDevice): return self.iss_data.is_above if self.iss_data else False @property - def sensor_class(self): + def device_class(self): """Return the class of this sensor.""" - return DEFAULT_SENSOR_CLASS + return DEFAULT_DEVICE_CLASS @property def device_state_attributes(self): diff --git a/homeassistant/components/binary_sensor/mqtt.py b/homeassistant/components/binary_sensor/mqtt.py index 8c8beaddb6e..3dbfffa75b6 100644 --- a/homeassistant/components/binary_sensor/mqtt.py +++ b/homeassistant/components/binary_sensor/mqtt.py @@ -11,12 +11,13 @@ import voluptuous as vol from homeassistant.core import callback import homeassistant.components.mqtt as mqtt from homeassistant.components.binary_sensor import ( - BinarySensorDevice, SENSOR_CLASSES) + BinarySensorDevice, DEVICE_CLASSES_SCHEMA) from homeassistant.const import ( CONF_NAME, CONF_VALUE_TEMPLATE, CONF_PAYLOAD_ON, CONF_PAYLOAD_OFF, - CONF_SENSOR_CLASS) + CONF_SENSOR_CLASS, CONF_DEVICE_CLASS) from homeassistant.components.mqtt import (CONF_STATE_TOPIC, CONF_QOS) import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.deprecation import get_deprecated _LOGGER = logging.getLogger(__name__) @@ -29,8 +30,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string, vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string, - vol.Optional(CONF_SENSOR_CLASS, default=None): - vol.Any(vol.In(SENSOR_CLASSES), vol.SetTo(None)), + vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, }) @@ -47,7 +48,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): hass, config.get(CONF_NAME), config.get(CONF_STATE_TOPIC), - config.get(CONF_SENSOR_CLASS), + get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS), config.get(CONF_QOS), config.get(CONF_PAYLOAD_ON), config.get(CONF_PAYLOAD_OFF), @@ -58,14 +59,14 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class MqttBinarySensor(BinarySensorDevice): """Representation a binary sensor that is updated by MQTT.""" - def __init__(self, hass, name, state_topic, sensor_class, qos, payload_on, + def __init__(self, hass, name, state_topic, device_class, qos, payload_on, payload_off, value_template): """Initialize the MQTT binary sensor.""" self._hass = hass self._name = name self._state = False self._state_topic = state_topic - self._sensor_class = sensor_class + self._device_class = device_class self._payload_on = payload_on self._payload_off = payload_off self._qos = qos @@ -101,6 +102,6 @@ class MqttBinarySensor(BinarySensorDevice): return self._state @property - def sensor_class(self): + def device_class(self): """Return the class of this sensor.""" - return self._sensor_class + return self._device_class diff --git a/homeassistant/components/binary_sensor/mysensors.py b/homeassistant/components/binary_sensor/mysensors.py index 6406dabd26f..3a0b09c0074 100644 --- a/homeassistant/components/binary_sensor/mysensors.py +++ b/homeassistant/components/binary_sensor/mysensors.py @@ -7,7 +7,7 @@ https://home-assistant.io/components/binary_sensor.mysensors/ import logging from homeassistant.components import mysensors -from homeassistant.components.binary_sensor import (SENSOR_CLASSES, +from homeassistant.components.binary_sensor import (DEVICE_CLASSES, BinarySensorDevice) from homeassistant.const import STATE_ON @@ -62,8 +62,8 @@ class MySensorsBinarySensor( return False @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" pres = self.gateway.const.Presentation class_map = { pres.S_DOOR: 'opening', @@ -78,5 +78,5 @@ class MySensorsBinarySensor( pres.S_VIBRATION: 'vibration', pres.S_MOISTURE: 'moisture', }) - if class_map.get(self.child_type) in SENSOR_CLASSES: + if class_map.get(self.child_type) in DEVICE_CLASSES: return class_map.get(self.child_type) diff --git a/homeassistant/components/binary_sensor/netatmo.py b/homeassistant/components/binary_sensor/netatmo.py index 661d1128086..ee7bc53c4cb 100644 --- a/homeassistant/components/binary_sensor/netatmo.py +++ b/homeassistant/components/binary_sensor/netatmo.py @@ -154,8 +154,8 @@ class NetatmoBinarySensor(BinarySensorDevice): return self._unique_id @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" if self._cameratype == "NACamera": return WELCOME_SENSOR_TYPES.get(self._sensor_name) elif self._cameratype == "NOC": diff --git a/homeassistant/components/binary_sensor/nx584.py b/homeassistant/components/binary_sensor/nx584.py index ad7612d11a6..6ffcb7b0cf3 100644 --- a/homeassistant/components/binary_sensor/nx584.py +++ b/homeassistant/components/binary_sensor/nx584.py @@ -12,7 +12,7 @@ import requests import voluptuous as vol from homeassistant.components.binary_sensor import ( - SENSOR_CLASSES, BinarySensorDevice, PLATFORM_SCHEMA) + DEVICE_CLASSES, BinarySensorDevice, PLATFORM_SCHEMA) from homeassistant.const import (CONF_HOST, CONF_PORT) import homeassistant.helpers.config_validation as cv @@ -28,7 +28,7 @@ DEFAULT_PORT = '5007' DEFAULT_SSL = False ZONE_TYPES_SCHEMA = vol.Schema({ - cv.positive_int: vol.In(SENSOR_CLASSES), + cv.positive_int: vol.In(DEVICE_CLASSES), }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -85,8 +85,8 @@ class NX584ZoneSensor(BinarySensorDevice): self._zone_type = zone_type @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return self._zone_type @property diff --git a/homeassistant/components/binary_sensor/octoprint.py b/homeassistant/components/binary_sensor/octoprint.py index 4284d2844bd..3fd92d1ceb1 100644 --- a/homeassistant/components/binary_sensor/octoprint.py +++ b/homeassistant/components/binary_sensor/octoprint.py @@ -99,8 +99,8 @@ class OctoPrintBinarySensor(BinarySensorDevice): return STATE_OFF @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return None def update(self): diff --git a/homeassistant/components/binary_sensor/rest.py b/homeassistant/components/binary_sensor/rest.py index 72f506eaefc..2e5de7e2f27 100644 --- a/homeassistant/components/binary_sensor/rest.py +++ b/homeassistant/components/binary_sensor/rest.py @@ -10,14 +10,15 @@ import voluptuous as vol from requests.auth import HTTPBasicAuth, HTTPDigestAuth from homeassistant.components.binary_sensor import ( - BinarySensorDevice, SENSOR_CLASSES_SCHEMA, PLATFORM_SCHEMA) + BinarySensorDevice, DEVICE_CLASSES_SCHEMA, PLATFORM_SCHEMA) from homeassistant.components.sensor.rest import RestData from homeassistant.const import ( CONF_PAYLOAD, CONF_NAME, CONF_VALUE_TEMPLATE, CONF_METHOD, CONF_RESOURCE, CONF_SENSOR_CLASS, CONF_VERIFY_SSL, CONF_USERNAME, CONF_PASSWORD, CONF_HEADERS, CONF_AUTHENTICATION, HTTP_BASIC_AUTHENTICATION, - HTTP_DIGEST_AUTHENTICATION) + HTTP_DIGEST_AUTHENTICATION, CONF_DEVICE_CLASS) import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.deprecation import get_deprecated _LOGGER = logging.getLogger(__name__) @@ -34,7 +35,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PASSWORD): cv.string, vol.Optional(CONF_PAYLOAD): cv.string, - vol.Optional(CONF_SENSOR_CLASS): SENSOR_CLASSES_SCHEMA, + vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_USERNAME): cv.string, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean, @@ -51,7 +53,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) headers = config.get(CONF_HEADERS) - sensor_class = config.get(CONF_SENSOR_CLASS) + device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) value_template = config.get(CONF_VALUE_TEMPLATE) if value_template is not None: value_template.hass = hass @@ -72,18 +74,18 @@ def setup_platform(hass, config, add_devices, discovery_info=None): return False add_devices([RestBinarySensor( - hass, rest, name, sensor_class, value_template)]) + hass, rest, name, device_class, value_template)]) class RestBinarySensor(BinarySensorDevice): """Representation of a REST binary sensor.""" - def __init__(self, hass, rest, name, sensor_class, value_template): + def __init__(self, hass, rest, name, device_class, value_template): """Initialize a REST binary sensor.""" self._hass = hass self.rest = rest self._name = name - self._sensor_class = sensor_class + self._device_class = device_class self._state = False self._previous_data = None self._value_template = value_template @@ -95,9 +97,9 @@ class RestBinarySensor(BinarySensorDevice): return self._name @property - def sensor_class(self): + def device_class(self): """Return the class of this sensor.""" - return self._sensor_class + return self._device_class @property def is_on(self): diff --git a/homeassistant/components/binary_sensor/sleepiq.py b/homeassistant/components/binary_sensor/sleepiq.py index 0409d04f9a5..f55eba82dbe 100644 --- a/homeassistant/components/binary_sensor/sleepiq.py +++ b/homeassistant/components/binary_sensor/sleepiq.py @@ -42,7 +42,7 @@ class IsInBedBinarySensor(sleepiq.SleepIQSensor, BinarySensorDevice): return self._state is True @property - def sensor_class(self): + def device_class(self): """Return the class of this sensor.""" return "occupancy" diff --git a/homeassistant/components/binary_sensor/template.py b/homeassistant/components/binary_sensor/template.py index fa60412c77f..8f11424f54c 100644 --- a/homeassistant/components/binary_sensor/template.py +++ b/homeassistant/components/binary_sensor/template.py @@ -12,14 +12,15 @@ import voluptuous as vol from homeassistant.core import callback from homeassistant.components.binary_sensor import ( BinarySensorDevice, ENTITY_ID_FORMAT, PLATFORM_SCHEMA, - SENSOR_CLASSES_SCHEMA) + DEVICE_CLASSES_SCHEMA) from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_ENTITY_ID, CONF_VALUE_TEMPLATE, - CONF_SENSOR_CLASS, CONF_SENSORS) + CONF_SENSOR_CLASS, CONF_SENSORS, CONF_DEVICE_CLASS) from homeassistant.exceptions import TemplateError from homeassistant.helpers.entity import async_generate_entity_id from homeassistant.helpers.event import async_track_state_change import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.deprecation import get_deprecated _LOGGER = logging.getLogger(__name__) @@ -27,7 +28,8 @@ SENSOR_SCHEMA = vol.Schema({ vol.Required(CONF_VALUE_TEMPLATE): cv.template, vol.Optional(ATTR_FRIENDLY_NAME): cv.string, vol.Optional(ATTR_ENTITY_ID): cv.entity_ids, - vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA + vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -45,7 +47,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): entity_ids = (device_config.get(ATTR_ENTITY_ID) or value_template.extract_entities()) friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) - sensor_class = device_config.get(CONF_SENSOR_CLASS) + device_class = get_deprecated( + device_config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) if value_template is not None: value_template.hass = hass @@ -55,7 +58,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): hass, device, friendly_name, - sensor_class, + device_class, value_template, entity_ids) ) @@ -70,14 +73,14 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): class BinarySensorTemplate(BinarySensorDevice): """A virtual binary sensor that triggers from another sensor.""" - def __init__(self, hass, device, friendly_name, sensor_class, + def __init__(self, hass, device, friendly_name, device_class, value_template, entity_ids): """Initialize the Template binary sensor.""" self.hass = hass self.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, device, hass=hass) self._name = friendly_name - self._sensor_class = sensor_class + self._device_class = device_class self._template = value_template self._state = None @@ -100,9 +103,9 @@ class BinarySensorTemplate(BinarySensorDevice): return self._state @property - def sensor_class(self): + def device_class(self): """Return the sensor class of the sensor.""" - return self._sensor_class + return self._device_class @property def should_poll(self): diff --git a/homeassistant/components/binary_sensor/threshold.py b/homeassistant/components/binary_sensor/threshold.py index 78338de64f7..be41fd96556 100644 --- a/homeassistant/components/binary_sensor/threshold.py +++ b/homeassistant/components/binary_sensor/threshold.py @@ -11,11 +11,12 @@ import voluptuous as vol import homeassistant.helpers.config_validation as cv from homeassistant.components.binary_sensor import ( - BinarySensorDevice, PLATFORM_SCHEMA, SENSOR_CLASSES_SCHEMA) + BinarySensorDevice, PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA) from homeassistant.const import ( CONF_NAME, CONF_ENTITY_ID, CONF_TYPE, STATE_UNKNOWN, CONF_SENSOR_CLASS, - ATTR_ENTITY_ID) + ATTR_ENTITY_ID, CONF_DEVICE_CLASS) from homeassistant.core import callback +from homeassistant.helpers.deprecation import get_deprecated from homeassistant.helpers.event import async_track_state_change _LOGGER = logging.getLogger(__name__) @@ -37,7 +38,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_THRESHOLD): vol.Coerce(float), vol.Required(CONF_TYPE): vol.In(SENSOR_TYPES), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA, + vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, }) @@ -48,11 +50,11 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): name = config.get(CONF_NAME) threshold = config.get(CONF_THRESHOLD) limit_type = config.get(CONF_TYPE) - sensor_class = config.get(CONF_SENSOR_CLASS) + device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) yield from async_add_devices( [ThresholdSensor(hass, entity_id, name, threshold, limit_type, - sensor_class)], True) + device_class)], True) return True @@ -60,14 +62,14 @@ class ThresholdSensor(BinarySensorDevice): """Representation of a Threshold sensor.""" def __init__(self, hass, entity_id, name, threshold, limit_type, - sensor_class): + device_class): """Initialize the Threshold sensor.""" self._hass = hass self._entity_id = entity_id self.is_upper = limit_type == 'upper' self._name = name self._threshold = threshold - self._sensor_class = sensor_class + self._device_class = device_class self._deviation = False self.sensor_value = 0 @@ -105,9 +107,9 @@ class ThresholdSensor(BinarySensorDevice): return False @property - def sensor_class(self): + def device_class(self): """Return the sensor class of the sensor.""" - return self._sensor_class + return self._device_class @property def device_state_attributes(self): diff --git a/homeassistant/components/binary_sensor/trend.py b/homeassistant/components/binary_sensor/trend.py index 7c38d4505ae..2c2a0563452 100644 --- a/homeassistant/components/binary_sensor/trend.py +++ b/homeassistant/components/binary_sensor/trend.py @@ -15,12 +15,14 @@ from homeassistant.components.binary_sensor import ( BinarySensorDevice, ENTITY_ID_FORMAT, PLATFORM_SCHEMA, - SENSOR_CLASSES_SCHEMA) + DEVICE_CLASSES_SCHEMA) from homeassistant.const import ( ATTR_FRIENDLY_NAME, ATTR_ENTITY_ID, CONF_SENSOR_CLASS, + CONF_DEVICE_CLASS, STATE_UNKNOWN,) +from homeassistant.helpers.deprecation import get_deprecated from homeassistant.helpers.entity import generate_entity_id from homeassistant.helpers.event import track_state_change @@ -34,8 +36,8 @@ SENSOR_SCHEMA = vol.Schema({ vol.Optional(CONF_ATTRIBUTE): cv.string, vol.Optional(ATTR_FRIENDLY_NAME): cv.string, vol.Optional(CONF_INVERT, default=False): cv.boolean, - vol.Optional(CONF_SENSOR_CLASS, default=None): SENSOR_CLASSES_SCHEMA - + vol.Optional(CONF_SENSOR_CLASS): DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -52,7 +54,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None): entity_id = device_config[ATTR_ENTITY_ID] attribute = device_config.get(CONF_ATTRIBUTE) friendly_name = device_config.get(ATTR_FRIENDLY_NAME, device) - sensor_class = device_config[CONF_SENSOR_CLASS] + device_class = get_deprecated( + device_config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) invert = device_config[CONF_INVERT] sensors.append( @@ -62,7 +65,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): friendly_name, entity_id, attribute, - sensor_class, + device_class, invert) ) if not sensors: @@ -76,7 +79,7 @@ class SensorTrend(BinarySensorDevice): """Representation of a trend Sensor.""" def __init__(self, hass, device_id, friendly_name, - target_entity, attribute, sensor_class, invert): + target_entity, attribute, device_class, invert): """Initialize the sensor.""" self._hass = hass self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id, @@ -84,7 +87,7 @@ class SensorTrend(BinarySensorDevice): self._name = friendly_name self._target_entity = target_entity self._attribute = attribute - self._sensor_class = sensor_class + self._device_class = device_class self._invert = invert self._state = None self.from_state = None @@ -111,9 +114,9 @@ class SensorTrend(BinarySensorDevice): return self._state @property - def sensor_class(self): + def device_class(self): """Return the sensor class of the sensor.""" - return self._sensor_class + return self._device_class @property def should_poll(self): diff --git a/homeassistant/components/binary_sensor/wink.py b/homeassistant/components/binary_sensor/wink.py index 4e1969de858..da60c54a0fd 100644 --- a/homeassistant/components/binary_sensor/wink.py +++ b/homeassistant/components/binary_sensor/wink.py @@ -107,8 +107,8 @@ class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity): return self.wink.state() @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return SENSOR_TYPES.get(self.capability) @@ -161,8 +161,8 @@ class WinkRemote(WinkBinarySensorDevice): } @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return None diff --git a/homeassistant/components/binary_sensor/zwave.py b/homeassistant/components/binary_sensor/zwave.py index 8dd02cc4b43..f9bd417768b 100644 --- a/homeassistant/components/binary_sensor/zwave.py +++ b/homeassistant/components/binary_sensor/zwave.py @@ -48,9 +48,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class ZWaveBinarySensor(BinarySensorDevice, zwave.ZWaveDeviceEntity): """Representation of a binary sensor within Z-Wave.""" - def __init__(self, value, sensor_class): + def __init__(self, value, device_class): """Initialize the sensor.""" - self._sensor_type = sensor_class + self._sensor_type = device_class zwave.ZWaveDeviceEntity.__init__(self, value, DOMAIN) @property @@ -59,8 +59,8 @@ class ZWaveBinarySensor(BinarySensorDevice, zwave.ZWaveDeviceEntity): return self._value.data @property - def sensor_class(self): - """Return the class of this sensor, from SENSOR_CLASSES.""" + def device_class(self): + """Return the class of this sensor, from DEVICE_CLASSES.""" return self._sensor_type @property @@ -72,9 +72,9 @@ class ZWaveBinarySensor(BinarySensorDevice, zwave.ZWaveDeviceEntity): class ZWaveTriggerSensor(ZWaveBinarySensor): """Representation of a stateless sensor within Z-Wave.""" - def __init__(self, value, sensor_class, hass, re_arm_sec=60): + def __init__(self, value, device_class, hass, re_arm_sec=60): """Initialize the sensor.""" - super(ZWaveTriggerSensor, self).__init__(value, sensor_class) + super(ZWaveTriggerSensor, self).__init__(value, device_class) self._hass = hass self.re_arm_sec = re_arm_sec self.invalidate_after = dt_util.utcnow() + datetime.timedelta( diff --git a/homeassistant/components/media_player/__init__.py b/homeassistant/components/media_player/__init__.py index a1077b1f132..e3c3170f6f1 100644 --- a/homeassistant/components/media_player/__init__.py +++ b/homeassistant/components/media_player/__init__.py @@ -20,6 +20,7 @@ from homeassistant.config import load_yaml_config_file from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_component import EntityComponent from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa +from homeassistant.helpers.deprecation import deprecated_substitute from homeassistant.components.http import HomeAssistantView, KEY_AUTHENTICATED from homeassistant.helpers.aiohttp_client import async_get_clientsession import homeassistant.helpers.config_validation as cv @@ -520,40 +521,9 @@ class MediaPlayerDevice(Entity): return None @property - def supported_media_commands(self): - """Flag media commands that are supported. - - DEPRECATED: Included for temporary custom platform compatibility. - """ - return None - - @property + @deprecated_substitute('supported_media_commands') def supported_features(self): """Flag media player features that are supported.""" - # Begin temporary transition logic - - if self.supported_media_commands is not None: - # If this platform is still using supported_media_commands, issue - # a logger warning once with instructions on how to fix it. - if not getattr(self, '_supported_features_warned', False): - def show_warning(): - """Show a deprecation warning in the log for this class.""" - import inspect - _LOGGER.warning( - "supported_media_commands is deprecated. Please " - "rename supported_media_commands to " - "supported_features in '%s' to ensure future support.", - inspect.getfile(self.__class__)) - # This is a temporary attribute. We don't want to pollute - # __init__ so it can be easily removed. - # pylint: disable=attribute-defined-outside-init - self._supported_features_warned = True - self.hass.add_job(show_warning) - - # Return the old property - return self.supported_media_commands - - # End temporary transition logic return 0 def turn_on(self): diff --git a/homeassistant/const.py b/homeassistant/const.py index 5df9bfe15f1..be33e12798f 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -78,6 +78,7 @@ CONF_CONDITION = 'condition' CONF_COVERS = 'covers' CONF_CUSTOMIZE = 'customize' CONF_DEVICE = 'device' +CONF_DEVICE_CLASS = 'device_class' CONF_DEVICES = 'devices' CONF_DISARM_AFTER_TRIGGER = 'disarm_after_trigger' CONF_DISCOVERY = 'discovery' @@ -291,6 +292,9 @@ ATTR_OPTION = 'option' # Bitfield of supported component features for the entity ATTR_SUPPORTED_FEATURES = 'supported_features' +# Class of device within its domain +ATTR_DEVICE_CLASS = 'device_class' + # #### SERVICES #### SERVICE_HOMEASSISTANT_STOP = 'stop' SERVICE_HOMEASSISTANT_RESTART = 'restart' diff --git a/homeassistant/helpers/deprecation.py b/homeassistant/helpers/deprecation.py new file mode 100644 index 00000000000..a2396b9d30f --- /dev/null +++ b/homeassistant/helpers/deprecation.py @@ -0,0 +1,56 @@ +"""Deprecation helpers for Home Assistant.""" + +import inspect +import logging + + +def deprecated_substitute(substitute_name): + """Help migrate properties to new names. + + When a property is added to replace an older property, this decorator can + be added to the new property, listing the old property as the substitute. + If the old property is defined, it's value will be used instead, and a log + warning will be issued alerting the user of the impending change. + """ + def decorator(func): + """Decorator function.""" + def func_wrapper(self): + """Wrapper for original function.""" + if hasattr(self, substitute_name): + # If this platform is still using the old property, issue + # a logger warning once with instructions on how to fix it. + warnings = getattr(func, '_deprecated_substitute_warnings', {}) + module_name = self.__module__ + if not warnings.get(module_name): + logger = logging.getLogger(module_name) + logger.warning( + "%s is deprecated. Please rename %s to " + "%s in '%s' to ensure future support.", + substitute_name, substitute_name, func.__name__, + inspect.getfile(self.__class__)) + warnings[module_name] = True + # pylint: disable=protected-access + func._deprecated_substitute_warnings = warnings + + # Return the old property + return getattr(self, substitute_name) + else: + return func(self) + return func_wrapper + return decorator + + +def get_deprecated(config, new_name, old_name, default=None): + """Allow an old config name to be deprecated with a replacement. + + If the new config isn't found, but the old one is, the old value is used + and a warning is issued to the user. + """ + if old_name in config: + module_name = inspect.getmodule(inspect.stack()[1][0]).__name__ + logger = logging.getLogger(module_name) + logger.warning( + "%s is deprecated. Please rename %s to %s in your " + "configuration file.", old_name, old_name, new_name) + return config.get(old_name) + return config.get(new_name, default) diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index a80f2f5edae..e66f49cc6dc 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -10,7 +10,7 @@ from homeassistant.const import ( ATTR_ASSUMED_STATE, ATTR_FRIENDLY_NAME, ATTR_HIDDEN, ATTR_ICON, ATTR_UNIT_OF_MEASUREMENT, DEVICE_DEFAULT_NAME, STATE_OFF, STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN, TEMP_CELSIUS, TEMP_FAHRENHEIT, - ATTR_ENTITY_PICTURE, ATTR_SUPPORTED_FEATURES) + ATTR_ENTITY_PICTURE, ATTR_SUPPORTED_FEATURES, ATTR_DEVICE_CLASS) from homeassistant.core import HomeAssistant, DOMAIN as CORE_DOMAIN from homeassistant.exceptions import NoEntitySpecifiedError from homeassistant.util import ensure_unique_string, slugify @@ -109,6 +109,11 @@ class Entity(object): """ return None + @property + def device_class(self) -> str: + """Return the class of this device, from component DEVICE_CLASSES.""" + return None + @property def unit_of_measurement(self): """Return the unit of measurement of this entity, if any.""" @@ -236,6 +241,7 @@ class Entity(object): self._attr_setter('assumed_state', bool, ATTR_ASSUMED_STATE, attr) self._attr_setter('supported_features', int, ATTR_SUPPORTED_FEATURES, attr) + self._attr_setter('device_class', str, ATTR_DEVICE_CLASS, attr) end = timer() diff --git a/tests/components/binary_sensor/test_binary_sensor.py b/tests/components/binary_sensor/test_binary_sensor.py index 96dda5ab3bb..89b6226c016 100644 --- a/tests/components/binary_sensor/test_binary_sensor.py +++ b/tests/components/binary_sensor/test_binary_sensor.py @@ -23,13 +23,3 @@ class TestBinarySensor(unittest.TestCase): new=True): self.assertEqual(STATE_ON, binary_sensor.BinarySensorDevice().state) - - def test_attributes(self): - """Test binary sensor attributes.""" - sensor = binary_sensor.BinarySensorDevice() - self.assertEqual({}, sensor.state_attributes) - with mock.patch('homeassistant.components.binary_sensor.' - 'BinarySensorDevice.sensor_class', - new='motion'): - self.assertEqual({'sensor_class': 'motion'}, - sensor.state_attributes) diff --git a/tests/components/binary_sensor/test_mqtt.py b/tests/components/binary_sensor/test_mqtt.py index 5e4a2640a34..f9630ae4b25 100644 --- a/tests/components/binary_sensor/test_mqtt.py +++ b/tests/components/binary_sensor/test_mqtt.py @@ -47,32 +47,32 @@ class TestSensorMQTT(unittest.TestCase): state = self.hass.states.get('binary_sensor.test') self.assertEqual(STATE_OFF, state.state) - def test_valid_sensor_class(self): + def test_valid_device_class(self): """Test the setting of a valid sensor class.""" self.hass.config.components = set(['mqtt']) assert setup_component(self.hass, binary_sensor.DOMAIN, { binary_sensor.DOMAIN: { 'platform': 'mqtt', 'name': 'test', - 'sensor_class': 'motion', + 'device_class': 'motion', 'state_topic': 'test-topic', } }) state = self.hass.states.get('binary_sensor.test') - self.assertEqual('motion', state.attributes.get('sensor_class')) + self.assertEqual('motion', state.attributes.get('device_class')) - def test_invalid_sensor_class(self): + def test_invalid_device_class(self): """Test the setting of an invalid sensor class.""" self.hass.config.components = set(['mqtt']) assert setup_component(self.hass, binary_sensor.DOMAIN, { binary_sensor.DOMAIN: { 'platform': 'mqtt', 'name': 'test', - 'sensor_class': 'abc123', + 'device_class': 'abc123', 'state_topic': 'test-topic', } }) state = self.hass.states.get('binary_sensor.test') - self.assertIsNone(state.attributes.get('sensor_class')) + self.assertIsNone(state) diff --git a/tests/components/binary_sensor/test_template.py b/tests/components/binary_sensor/test_template.py index 98462083e6f..cb526851710 100644 --- a/tests/components/binary_sensor/test_template.py +++ b/tests/components/binary_sensor/test_template.py @@ -36,7 +36,7 @@ class TestBinarySensorTemplate(unittest.TestCase): 'test': { 'friendly_name': 'virtual thingy', 'value_template': '{{ foo }}', - 'sensor_class': 'motion', + 'device_class': 'motion', }, }, }, @@ -66,7 +66,7 @@ class TestBinarySensorTemplate(unittest.TestCase): } }) - def test_setup_invalid_sensor_class(self): + def test_setup_invalid_device_class(self): """"Test setup with invalid sensor class.""" with assert_setup_component(0): assert bootstrap.setup_component(self.hass, 'binary_sensor', { @@ -75,7 +75,7 @@ class TestBinarySensorTemplate(unittest.TestCase): 'sensors': { 'test': { 'value_template': '{{ foo }}', - 'sensor_class': 'foobarnotreal', + 'device_class': 'foobarnotreal', }, }, } @@ -89,7 +89,7 @@ class TestBinarySensorTemplate(unittest.TestCase): 'platform': 'template', 'sensors': { 'test': { - 'sensor_class': 'motion', + 'device_class': 'motion', }, } } @@ -103,7 +103,7 @@ class TestBinarySensorTemplate(unittest.TestCase): template_hlpr.Template('{{ 1 > 1 }}', self.hass), MATCH_ALL ).result() self.assertFalse(vs.should_poll) - self.assertEqual('motion', vs.sensor_class) + self.assertEqual('motion', vs.device_class) self.assertEqual('Parent', vs.name) vs.update() diff --git a/tests/helpers/test_entity.py b/tests/helpers/test_entity.py index 061c206c116..c114478319f 100644 --- a/tests/helpers/test_entity.py +++ b/tests/helpers/test_entity.py @@ -2,12 +2,13 @@ # pylint: disable=protected-access import asyncio from unittest.mock import MagicMock +from unittest.mock import patch import pytest import homeassistant.helpers.entity as entity from homeassistant.helpers.customize import set_customize -from homeassistant.const import ATTR_HIDDEN +from homeassistant.const import ATTR_HIDDEN, ATTR_DEVICE_CLASS from tests.common import get_test_home_assistant @@ -119,3 +120,13 @@ class TestHelpersEntity(object): ent = AsyncEntity() ent.update() assert len(async_update) == 1 + + def test_device_class(self): + """Test device class attribute.""" + state = self.hass.states.get(self.entity.entity_id) + assert state.attributes.get(ATTR_DEVICE_CLASS) is None + with patch('homeassistant.helpers.entity.Entity.device_class', + new='test_class'): + self.entity.update_ha_state() + state = self.hass.states.get(self.entity.entity_id) + assert state.attributes.get(ATTR_DEVICE_CLASS) == 'test_class'