From 5db1474099e02bdf2e94797fdcd9d5ca665d01c8 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Sat, 24 Oct 2020 21:45:01 +0200 Subject: [PATCH] Add device_class information to onewire sensors (#42308) --- homeassistant/components/onewire/sensor.py | 74 +++++++++++-------- .../onewire/test_entity_owserver.py | 36 ++++++++- .../components/onewire/test_entity_sysbus.py | 10 ++- 3 files changed, 87 insertions(+), 33 deletions(-) diff --git a/homeassistant/components/onewire/sensor.py b/homeassistant/components/onewire/sensor.py index 7952e5ca7de..510d8601fbf 100644 --- a/homeassistant/components/onewire/sensor.py +++ b/homeassistant/components/onewire/sensor.py @@ -2,6 +2,7 @@ from glob import glob import logging import os +from typing import Any, Dict, Optional from pi1wire import InvalidCRCException, Pi1Wire, UnsupportResponseException from pyownet import protocol @@ -13,6 +14,12 @@ from homeassistant.const import ( CONF_HOST, CONF_PORT, CONF_TYPE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLTAGE, ELECTRICAL_CURRENT_AMPERE, LIGHT_LUX, PERCENTAGE, @@ -22,6 +29,7 @@ from homeassistant.const import ( ) import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity +from homeassistant.helpers.typing import StateType from .const import ( CONF_MOUNT_DIR, @@ -83,31 +91,31 @@ HOBBYBOARD_EF = { } SENSOR_TYPES = { - # SensorType: [ Measured unit, Unit ] - "temperature": ["temperature", TEMP_CELSIUS], - "humidity": ["humidity", PERCENTAGE], - "humidity_hih3600": ["humidity", PERCENTAGE], - "humidity_hih4000": ["humidity", PERCENTAGE], - "humidity_hih5030": ["humidity", PERCENTAGE], - "humidity_htm1735": ["humidity", PERCENTAGE], - "humidity_raw": ["humidity", PERCENTAGE], - "pressure": ["pressure", PRESSURE_MBAR], - "illuminance": ["illuminance", LIGHT_LUX], - "wetness_0": ["wetness", PERCENTAGE], - "wetness_1": ["wetness", PERCENTAGE], - "wetness_2": ["wetness", PERCENTAGE], - "wetness_3": ["wetness", PERCENTAGE], - "moisture_0": ["moisture", PRESSURE_CBAR], - "moisture_1": ["moisture", PRESSURE_CBAR], - "moisture_2": ["moisture", PRESSURE_CBAR], - "moisture_3": ["moisture", PRESSURE_CBAR], - "counter_a": ["counter", "count"], - "counter_b": ["counter", "count"], - "HobbyBoard": ["none", "none"], - "voltage": ["voltage", VOLT], - "voltage_VAD": ["voltage", VOLT], - "voltage_VDD": ["voltage", VOLT], - "current": ["current", ELECTRICAL_CURRENT_AMPERE], + # SensorType: [ Measured unit, Unit, DeviceClass ] + "temperature": ["temperature", TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE], + "humidity": ["humidity", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "humidity_hih3600": ["humidity", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "humidity_hih4000": ["humidity", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "humidity_hih5030": ["humidity", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "humidity_htm1735": ["humidity", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "humidity_raw": ["humidity", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "pressure": ["pressure", PRESSURE_MBAR, DEVICE_CLASS_PRESSURE], + "illuminance": ["illuminance", LIGHT_LUX, DEVICE_CLASS_ILLUMINANCE], + "wetness_0": ["wetness", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "wetness_1": ["wetness", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "wetness_2": ["wetness", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "wetness_3": ["wetness", PERCENTAGE, DEVICE_CLASS_HUMIDITY], + "moisture_0": ["moisture", PRESSURE_CBAR, DEVICE_CLASS_PRESSURE], + "moisture_1": ["moisture", PRESSURE_CBAR, DEVICE_CLASS_PRESSURE], + "moisture_2": ["moisture", PRESSURE_CBAR, DEVICE_CLASS_PRESSURE], + "moisture_3": ["moisture", PRESSURE_CBAR, DEVICE_CLASS_PRESSURE], + "counter_a": ["counter", "count", None], + "counter_b": ["counter", "count", None], + "HobbyBoard": ["none", "none", None], + "voltage": ["voltage", VOLT, DEVICE_CLASS_VOLTAGE], + "voltage_VAD": ["voltage", VOLT, DEVICE_CLASS_VOLTAGE], + "voltage_VDD": ["voltage", VOLT, DEVICE_CLASS_VOLTAGE], + "current": ["current", ELECTRICAL_CURRENT_AMPERE, DEVICE_CLASS_CURRENT], } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( @@ -282,34 +290,40 @@ class OneWire(Entity): """Initialize the sensor.""" self._name = f"{name} {sensor_type.capitalize()}" self._device_file = device_file + self._device_class = SENSOR_TYPES[sensor_type][2] self._unit_of_measurement = SENSOR_TYPES[sensor_type][1] self._state = None self._value_raw = None @property - def name(self): + def name(self) -> Optional[str]: """Return the name of the sensor.""" return self._name @property - def state(self): + def state(self) -> StateType: """Return the state of the sensor.""" if "count" in self._unit_of_measurement: return int(self._state) return self._state @property - def unit_of_measurement(self): + def device_class(self) -> Optional[str]: + """Return the class of this device.""" + return self._device_class + + @property + def unit_of_measurement(self) -> Optional[str]: """Return the unit the value is expressed in.""" return self._unit_of_measurement @property - def device_state_attributes(self): + def device_state_attributes(self) -> Optional[Dict[str, Any]]: """Return the state attributes of the sensor.""" return {"device_file": self._device_file, "raw_value": self._value_raw} @property - def unique_id(self) -> str: + def unique_id(self) -> Optional[str]: """Return a unique ID.""" return self._device_file diff --git a/tests/components/onewire/test_entity_owserver.py b/tests/components/onewire/test_entity_owserver.py index be716eb7d10..517bf81ca18 100644 --- a/tests/components/onewire/test_entity_owserver.py +++ b/tests/components/onewire/test_entity_owserver.py @@ -9,6 +9,12 @@ from homeassistant.components.onewire.const import ( ) from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN from homeassistant.const import ( + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLTAGE, ELECTRICAL_CURRENT_AMPERE, LIGHT_LUX, PERCENTAGE, @@ -22,7 +28,7 @@ from tests.async_mock import patch from tests.common import mock_registry MOCK_CONFIG = { - "sensor": { + SENSOR_DOMAIN: { "platform": DOMAIN, "host": "localhost", "port": DEFAULT_OWSERVER_PORT, @@ -42,6 +48,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 25.123", "result": "25.1", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -53,6 +60,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 25.123", "result": "25.1", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, { "entity_id": "sensor.12_111111111111_pressure", @@ -60,6 +68,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 1025.123", "result": "1025.1", "unit": PRESSURE_MBAR, + "class": DEVICE_CLASS_PRESSURE, }, ] }, @@ -71,6 +80,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 251123", "result": "251123", "unit": "count", + "class": None, }, { "entity_id": "sensor.1d_111111111111_counter_b", @@ -78,6 +88,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 248125", "result": "248125", "unit": "count", + "class": None, }, ] }, @@ -89,6 +100,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": ProtocolError, "result": "unknown", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -100,6 +112,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 25.123", "result": "25.1", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, { "entity_id": "sensor.26_111111111111_humidity", @@ -107,6 +120,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 72.7563", "result": "72.8", "unit": PERCENTAGE, + "class": DEVICE_CLASS_HUMIDITY, }, { "entity_id": "sensor.26_111111111111_humidity_hih3600", @@ -114,6 +128,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 73.7563", "result": "73.8", "unit": PERCENTAGE, + "class": DEVICE_CLASS_HUMIDITY, }, { "entity_id": "sensor.26_111111111111_humidity_hih4000", @@ -121,6 +136,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 74.7563", "result": "74.8", "unit": PERCENTAGE, + "class": DEVICE_CLASS_HUMIDITY, }, { "entity_id": "sensor.26_111111111111_humidity_hih5030", @@ -128,6 +144,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 75.7563", "result": "75.8", "unit": PERCENTAGE, + "class": DEVICE_CLASS_HUMIDITY, }, { "entity_id": "sensor.26_111111111111_humidity_htm1735", @@ -135,6 +152,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": ProtocolError, "result": "unknown", "unit": PERCENTAGE, + "class": DEVICE_CLASS_HUMIDITY, }, { "entity_id": "sensor.26_111111111111_pressure", @@ -142,6 +160,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 969.265", "result": "969.3", "unit": PRESSURE_MBAR, + "class": DEVICE_CLASS_PRESSURE, }, { "entity_id": "sensor.26_111111111111_illuminance", @@ -149,6 +168,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 65.8839", "result": "65.9", "unit": LIGHT_LUX, + "class": DEVICE_CLASS_ILLUMINANCE, }, { "entity_id": "sensor.26_111111111111_voltage_vad", @@ -156,6 +176,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 2.97", "result": "3.0", "unit": VOLT, + "class": DEVICE_CLASS_VOLTAGE, }, { "entity_id": "sensor.26_111111111111_voltage_vdd", @@ -163,6 +184,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 4.74", "result": "4.7", "unit": VOLT, + "class": DEVICE_CLASS_VOLTAGE, }, { "entity_id": "sensor.26_111111111111_current", @@ -170,6 +192,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 1", "result": "1.0", "unit": ELECTRICAL_CURRENT_AMPERE, + "class": DEVICE_CLASS_CURRENT, }, ] }, @@ -181,6 +204,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 26.984", "result": "27.0", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -192,6 +216,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 28.243", "result": "28.2", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -203,6 +228,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 29.123", "result": "29.1", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -217,6 +243,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 67.745", "result": "67.7", "unit": PERCENTAGE, + "class": DEVICE_CLASS_HUMIDITY, }, { "entity_id": "sensor.ef_111111111111_humidity_raw", @@ -224,6 +251,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 65.541", "result": "65.5", "unit": PERCENTAGE, + "class": DEVICE_CLASS_HUMIDITY, }, { "entity_id": "sensor.ef_111111111111_temperature", @@ -231,6 +259,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 25.123", "result": "25.1", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ], }, @@ -249,6 +278,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 41.745", "result": "41.7", "unit": PERCENTAGE, + "class": DEVICE_CLASS_HUMIDITY, }, { "entity_id": "sensor.ef_111111111112_wetness_1", @@ -256,6 +286,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 42.541", "result": "42.5", "unit": PERCENTAGE, + "class": DEVICE_CLASS_HUMIDITY, }, { "entity_id": "sensor.ef_111111111112_moisture_2", @@ -263,6 +294,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 43.123", "result": "43.1", "unit": PRESSURE_CBAR, + "class": DEVICE_CLASS_PRESSURE, }, { "entity_id": "sensor.ef_111111111112_moisture_3", @@ -270,6 +302,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": b" 44.123", "result": "44.1", "unit": PRESSURE_CBAR, + "class": DEVICE_CLASS_PRESSURE, }, ], }, @@ -308,5 +341,6 @@ async def test_owserver_setup_valid_device(hass, device_id): assert registry_entry is not None assert registry_entry.unique_id == expected_sensor["unique_id"] assert registry_entry.unit_of_measurement == expected_sensor["unit"] + assert registry_entry.device_class == expected_sensor["class"] state = hass.states.get(entity_id) assert state.state == expected_sensor["result"] diff --git a/tests/components/onewire/test_entity_sysbus.py b/tests/components/onewire/test_entity_sysbus.py index ae90f831e37..dc4673e42a7 100644 --- a/tests/components/onewire/test_entity_sysbus.py +++ b/tests/components/onewire/test_entity_sysbus.py @@ -4,14 +4,14 @@ import pytest from homeassistant.components.onewire.const import DEFAULT_SYSBUS_MOUNT_DIR, DOMAIN from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN -from homeassistant.const import TEMP_CELSIUS +from homeassistant.const import DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS from homeassistant.setup import async_setup_component from tests.async_mock import patch from tests.common import mock_registry MOCK_CONFIG = { - "sensor": { + SENSOR_DOMAIN: { "platform": DOMAIN, "mount_dir": DEFAULT_SYSBUS_MOUNT_DIR, "names": { @@ -30,6 +30,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": 25.123, "result": "25.1", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -43,6 +44,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": FileNotFoundError, "result": "unknown", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -55,6 +57,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": InvalidCRCException, "result": "unknown", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -66,6 +69,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": 29.993, "result": "30.0", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -77,6 +81,7 @@ MOCK_DEVICE_SENSORS = { "injected_value": UnsupportResponseException, "result": "unknown", "unit": TEMP_CELSIUS, + "class": DEVICE_CLASS_TEMPERATURE, }, ] }, @@ -120,5 +125,6 @@ async def test_onewiredirect_setup_valid_device(hass, device_id): assert registry_entry is not None assert registry_entry.unique_id == expected_sensor["unique_id"] assert registry_entry.unit_of_measurement == expected_sensor["unit"] + assert registry_entry.device_class == expected_sensor["class"] state = hass.states.get(entity_id) assert state.state == expected_sensor["result"]