diff --git a/homeassistant/components/rest/binary_sensor.py b/homeassistant/components/rest/binary_sensor.py index a90c5bd7c77..d6bdefee563 100644 --- a/homeassistant/components/rest/binary_sensor.py +++ b/homeassistant/components/rest/binary_sensor.py @@ -85,14 +85,14 @@ class RestBinarySensor(RestEntity, BinarySensorEntity): resource_template, ): """Initialize a REST binary sensor.""" - super().__init__( - coordinator, rest, name, device_class, resource_template, force_update - ) + super().__init__(coordinator, rest, name, resource_template, force_update) self._state = False self._previous_data = None self._value_template = value_template self._is_on = None + self._attr_device_class = device_class + @property def is_on(self): """Return true if the binary sensor is on.""" diff --git a/homeassistant/components/rest/entity.py b/homeassistant/components/rest/entity.py index acfe5a2dfc5..064396af415 100644 --- a/homeassistant/components/rest/entity.py +++ b/homeassistant/components/rest/entity.py @@ -18,7 +18,6 @@ class RestEntity(Entity): coordinator: DataUpdateCoordinator[Any], rest: RestData, name, - device_class, resource_template, force_update, ) -> None: @@ -26,7 +25,6 @@ class RestEntity(Entity): self.coordinator = coordinator self.rest = rest self._name = name - self._device_class = device_class self._resource_template = resource_template self._force_update = force_update super().__init__() @@ -36,11 +34,6 @@ class RestEntity(Entity): """Return the name of the sensor.""" return self._name - @property - def device_class(self): - """Return the class of this sensor.""" - return self._device_class - @property def force_update(self): """Force update.""" diff --git a/homeassistant/components/rest/schema.py b/homeassistant/components/rest/schema.py index bedd02d272a..a4b87051c4b 100644 --- a/homeassistant/components/rest/schema.py +++ b/homeassistant/components/rest/schema.py @@ -9,7 +9,9 @@ from homeassistant.components.binary_sensor import ( from homeassistant.components.sensor import ( DEVICE_CLASSES_SCHEMA as SENSOR_DEVICE_CLASSES_SCHEMA, DOMAIN as SENSOR_DOMAIN, + STATE_CLASSES_SCHEMA, ) +from homeassistant.components.sensor.const import CONF_STATE_CLASS from homeassistant.const import ( CONF_AUTHENTICATION, CONF_DEVICE_CLASS, @@ -66,6 +68,7 @@ SENSOR_SCHEMA = { vol.Optional(CONF_NAME, default=DEFAULT_SENSOR_NAME): cv.string, vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, vol.Optional(CONF_DEVICE_CLASS): SENSOR_DEVICE_CLASSES_SCHEMA, + vol.Optional(CONF_STATE_CLASS): STATE_CLASSES_SCHEMA, vol.Optional(CONF_JSON_ATTRS, default=[]): cv.ensure_list_csv, vol.Optional(CONF_JSON_ATTRS_PATH): cv.string, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, diff --git a/homeassistant/components/rest/sensor.py b/homeassistant/components/rest/sensor.py index f0355014986..9f8c33ad6df 100644 --- a/homeassistant/components/rest/sensor.py +++ b/homeassistant/components/rest/sensor.py @@ -8,6 +8,7 @@ import voluptuous as vol import xmltodict from homeassistant.components.sensor import ( + CONF_STATE_CLASS, DOMAIN as SENSOR_DOMAIN, PLATFORM_SCHEMA, SensorEntity, @@ -60,6 +61,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= name = conf.get(CONF_NAME) unit = conf.get(CONF_UNIT_OF_MEASUREMENT) device_class = conf.get(CONF_DEVICE_CLASS) + state_class = conf.get(CONF_STATE_CLASS) json_attrs = conf.get(CONF_JSON_ATTRS) json_attrs_path = conf.get(CONF_JSON_ATTRS_PATH) value_template = conf.get(CONF_VALUE_TEMPLATE) @@ -77,6 +79,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= name, unit, device_class, + state_class, value_template, json_attrs, force_update, @@ -97,6 +100,7 @@ class RestSensor(RestEntity, SensorEntity): name, unit_of_measurement, device_class, + state_class, value_template, json_attrs, force_update, @@ -104,9 +108,7 @@ class RestSensor(RestEntity, SensorEntity): json_attrs_path, ): """Initialize the REST sensor.""" - super().__init__( - coordinator, rest, name, device_class, resource_template, force_update - ) + super().__init__(coordinator, rest, name, resource_template, force_update) self._state = None self._unit_of_measurement = unit_of_measurement self._value_template = value_template @@ -114,10 +116,9 @@ class RestSensor(RestEntity, SensorEntity): self._attributes = None self._json_attrs_path = json_attrs_path - @property - def native_unit_of_measurement(self): - """Return the unit the value is expressed in.""" - return self._unit_of_measurement + self._attr_native_unit_of_measurement = self._unit_of_measurement + self._attr_device_class = device_class + self._attr_state_class = state_class @property def native_value(self): diff --git a/homeassistant/components/rest/switch.py b/homeassistant/components/rest/switch.py index e8ae1dee015..66a5f21cc40 100644 --- a/homeassistant/components/rest/switch.py +++ b/homeassistant/components/rest/switch.py @@ -6,8 +6,13 @@ import aiohttp import async_timeout import voluptuous as vol -from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchEntity +from homeassistant.components.switch import ( + DEVICE_CLASSES_SCHEMA, + PLATFORM_SCHEMA, + SwitchEntity, +) from homeassistant.const import ( + CONF_DEVICE_CLASS, CONF_HEADERS, CONF_METHOD, CONF_NAME, @@ -51,6 +56,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( vol.Lower, vol.In(SUPPORT_REST_METHODS) ), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA, vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, vol.Inclusive(CONF_USERNAME, "authentication"): cv.string, vol.Inclusive(CONF_PASSWORD, "authentication"): cv.string, @@ -68,6 +74,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= headers = config.get(CONF_HEADERS) params = config.get(CONF_PARAMS) name = config.get(CONF_NAME) + device_class = config.get(CONF_DEVICE_CLASS) username = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) resource = config.get(CONF_RESOURCE) @@ -89,6 +96,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= try: switch = RestSwitch( name, + device_class, resource, state_resource, method, @@ -122,6 +130,7 @@ class RestSwitch(SwitchEntity): def __init__( self, name, + device_class, resource, state_resource, method, @@ -149,6 +158,8 @@ class RestSwitch(SwitchEntity): self._timeout = timeout self._verify_ssl = verify_ssl + self._attr_device_class = device_class + @property def name(self): """Return the name of the switch.""" diff --git a/tests/components/rest/test_binary_sensor.py b/tests/components/rest/test_binary_sensor.py index d443710f9b2..0af82f9ab5a 100644 --- a/tests/components/rest/test_binary_sensor.py +++ b/tests/components/rest/test_binary_sensor.py @@ -10,6 +10,7 @@ import respx from homeassistant import config as hass_config import homeassistant.components.binary_sensor as binary_sensor from homeassistant.const import ( + ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, CONTENT_TYPE_JSON, SERVICE_RELOAD, @@ -164,6 +165,7 @@ async def test_setup_get(hass): "username": "my username", "password": "my password", "headers": {"Accept": CONTENT_TYPE_JSON}, + "device_class": binary_sensor.DEVICE_CLASS_PLUG, } }, ) @@ -171,6 +173,10 @@ async def test_setup_get(hass): await hass.async_block_till_done() assert len(hass.states.async_all("binary_sensor")) == 1 + state = hass.states.get("binary_sensor.foo") + assert state.state == STATE_OFF + assert state.attributes[ATTR_DEVICE_CLASS] == binary_sensor.DEVICE_CLASS_PLUG + @respx.mock async def test_setup_get_digest_auth(hass): diff --git a/tests/components/rest/test_sensor.py b/tests/components/rest/test_sensor.py index f50f5aba3bc..a59cb99bcdf 100644 --- a/tests/components/rest/test_sensor.py +++ b/tests/components/rest/test_sensor.py @@ -10,12 +10,15 @@ from homeassistant import config as hass_config from homeassistant.components.homeassistant import SERVICE_UPDATE_ENTITY import homeassistant.components.sensor as sensor from homeassistant.const import ( + ATTR_DEVICE_CLASS, ATTR_ENTITY_ID, ATTR_UNIT_OF_MEASUREMENT, CONTENT_TYPE_JSON, DATA_MEGABYTES, + DEVICE_CLASS_TEMPERATURE, SERVICE_RELOAD, STATE_UNKNOWN, + TEMP_CELSIUS, ) from homeassistant.setup import async_setup_component @@ -177,13 +180,15 @@ async def test_setup_get(hass): "method": "GET", "value_template": "{{ value_json.key }}", "name": "foo", - "unit_of_measurement": DATA_MEGABYTES, + "unit_of_measurement": TEMP_CELSIUS, "verify_ssl": "true", "timeout": 30, "authentication": "basic", "username": "my username", "password": "my password", "headers": {"Accept": CONTENT_TYPE_JSON}, + "device_class": DEVICE_CLASS_TEMPERATURE, + "state_class": sensor.STATE_CLASS_MEASUREMENT, } }, ) @@ -200,7 +205,11 @@ async def test_setup_get(hass): blocking=True, ) await hass.async_block_till_done() - assert hass.states.get("sensor.foo").state == "" + state = hass.states.get("sensor.foo") + assert state.state == "" + assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == TEMP_CELSIUS + assert state.attributes[ATTR_DEVICE_CLASS] == DEVICE_CLASS_TEMPERATURE + assert state.attributes[sensor.ATTR_STATE_CLASS] == sensor.STATE_CLASS_MEASUREMENT @respx.mock diff --git a/tests/components/rest/test_switch.py b/tests/components/rest/test_switch.py index 48f63ddabc7..4370386dcff 100644 --- a/tests/components/rest/test_switch.py +++ b/tests/components/rest/test_switch.py @@ -6,7 +6,7 @@ import aiohttp from homeassistant.components.rest import DOMAIN import homeassistant.components.rest.switch as rest -from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN +from homeassistant.components.switch import DEVICE_CLASS_SWITCH, DOMAIN as SWITCH_DOMAIN from homeassistant.const import ( CONF_HEADERS, CONF_NAME, @@ -23,6 +23,7 @@ from tests.common import assert_setup_component """Tests for setting up the REST switch platform.""" NAME = "foo" +DEVICE_CLASS = DEVICE_CLASS_SWITCH METHOD = "post" RESOURCE = "http://localhost/" STATE_RESOURCE = RESOURCE @@ -158,6 +159,7 @@ def _setup_test_switch(hass): body_off = Template("off", hass) switch = rest.RestSwitch( NAME, + DEVICE_CLASS, RESOURCE, STATE_RESOURCE, METHOD, @@ -180,6 +182,12 @@ def test_name(hass): assert switch.name == NAME +def test_device_class(hass): + """Test the name.""" + switch, body_on, body_off = _setup_test_switch(hass) + assert switch.device_class == DEVICE_CLASS + + def test_is_on_before_update(hass): """Test is_on in initial state.""" switch, body_on, body_off = _setup_test_switch(hass)