Align number and sensor device classes (#81909)
* Align number and sensor device classes * Add tests * Tweak testspull/65158/head^2
parent
18e30e7c06
commit
b6586d5c34
|
@ -55,8 +55,249 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
class NumberDeviceClass(StrEnum):
|
class NumberDeviceClass(StrEnum):
|
||||||
"""Device class for numbers."""
|
"""Device class for numbers."""
|
||||||
|
|
||||||
# temperature (C/F)
|
# NumberDeviceClass should be aligned with SensorDeviceClass
|
||||||
|
|
||||||
|
APPARENT_POWER = "apparent_power"
|
||||||
|
"""Apparent power.
|
||||||
|
|
||||||
|
Unit of measurement: `VA`
|
||||||
|
"""
|
||||||
|
|
||||||
|
AQI = "aqi"
|
||||||
|
"""Air Quality Index.
|
||||||
|
|
||||||
|
Unit of measurement: `None`
|
||||||
|
"""
|
||||||
|
|
||||||
|
BATTERY = "battery"
|
||||||
|
"""Percentage of battery that is left.
|
||||||
|
|
||||||
|
Unit of measurement: `%`
|
||||||
|
"""
|
||||||
|
|
||||||
|
CO = "carbon_monoxide"
|
||||||
|
"""Carbon Monoxide gas concentration.
|
||||||
|
|
||||||
|
Unit of measurement: `ppm` (parts per million)
|
||||||
|
"""
|
||||||
|
|
||||||
|
CO2 = "carbon_dioxide"
|
||||||
|
"""Carbon Dioxide gas concentration.
|
||||||
|
|
||||||
|
Unit of measurement: `ppm` (parts per million)
|
||||||
|
"""
|
||||||
|
|
||||||
|
CURRENT = "current"
|
||||||
|
"""Current.
|
||||||
|
|
||||||
|
Unit of measurement: `A`
|
||||||
|
"""
|
||||||
|
|
||||||
|
DISTANCE = "distance"
|
||||||
|
"""Generic distance.
|
||||||
|
|
||||||
|
Unit of measurement: `LENGTH_*` units
|
||||||
|
- SI /metric: `mm`, `cm`, `m`, `km`
|
||||||
|
- USCS / imperial: `in`, `ft`, `yd`, `mi`
|
||||||
|
"""
|
||||||
|
|
||||||
|
ENERGY = "energy"
|
||||||
|
"""Energy.
|
||||||
|
|
||||||
|
Unit of measurement: `Wh`, `kWh`, `MWh`, `GJ`
|
||||||
|
"""
|
||||||
|
|
||||||
|
FREQUENCY = "frequency"
|
||||||
|
"""Frequency.
|
||||||
|
|
||||||
|
Unit of measurement: `Hz`, `kHz`, `MHz`, `GHz`
|
||||||
|
"""
|
||||||
|
|
||||||
|
GAS = "gas"
|
||||||
|
"""Gas.
|
||||||
|
|
||||||
|
Unit of measurement: `m³`, `ft³`
|
||||||
|
"""
|
||||||
|
|
||||||
|
HUMIDITY = "humidity"
|
||||||
|
"""Relative humidity.
|
||||||
|
|
||||||
|
Unit of measurement: `%`
|
||||||
|
"""
|
||||||
|
|
||||||
|
ILLUMINANCE = "illuminance"
|
||||||
|
"""Illuminance.
|
||||||
|
|
||||||
|
Unit of measurement: `lx`, `lm`
|
||||||
|
"""
|
||||||
|
|
||||||
|
MOISTURE = "moisture"
|
||||||
|
"""Moisture.
|
||||||
|
|
||||||
|
Unit of measurement: `%`
|
||||||
|
"""
|
||||||
|
|
||||||
|
MONETARY = "monetary"
|
||||||
|
"""Amount of money.
|
||||||
|
|
||||||
|
Unit of measurement: ISO4217 currency code
|
||||||
|
|
||||||
|
See https://en.wikipedia.org/wiki/ISO_4217#Active_codes for active codes
|
||||||
|
"""
|
||||||
|
|
||||||
|
NITROGEN_DIOXIDE = "nitrogen_dioxide"
|
||||||
|
"""Amount of NO2.
|
||||||
|
|
||||||
|
Unit of measurement: `µg/m³`
|
||||||
|
"""
|
||||||
|
|
||||||
|
NITROGEN_MONOXIDE = "nitrogen_monoxide"
|
||||||
|
"""Amount of NO.
|
||||||
|
|
||||||
|
Unit of measurement: `µg/m³`
|
||||||
|
"""
|
||||||
|
|
||||||
|
NITROUS_OXIDE = "nitrous_oxide"
|
||||||
|
"""Amount of N2O.
|
||||||
|
|
||||||
|
Unit of measurement: `µg/m³`
|
||||||
|
"""
|
||||||
|
|
||||||
|
OZONE = "ozone"
|
||||||
|
"""Amount of O3.
|
||||||
|
|
||||||
|
Unit of measurement: `µg/m³`
|
||||||
|
"""
|
||||||
|
|
||||||
|
PM1 = "pm1"
|
||||||
|
"""Particulate matter <= 0.1 μm.
|
||||||
|
|
||||||
|
Unit of measurement: `µg/m³`
|
||||||
|
"""
|
||||||
|
|
||||||
|
PM10 = "pm10"
|
||||||
|
"""Particulate matter <= 10 μm.
|
||||||
|
|
||||||
|
Unit of measurement: `µg/m³`
|
||||||
|
"""
|
||||||
|
|
||||||
|
PM25 = "pm25"
|
||||||
|
"""Particulate matter <= 2.5 μm.
|
||||||
|
|
||||||
|
Unit of measurement: `µg/m³`
|
||||||
|
"""
|
||||||
|
|
||||||
|
POWER_FACTOR = "power_factor"
|
||||||
|
"""Power factor.
|
||||||
|
|
||||||
|
Unit of measurement: `%`
|
||||||
|
"""
|
||||||
|
|
||||||
|
POWER = "power"
|
||||||
|
"""Power.
|
||||||
|
|
||||||
|
Unit of measurement: `W`, `kW`
|
||||||
|
"""
|
||||||
|
|
||||||
|
PRECIPITATION_INTENSITY = "precipitation_intensity"
|
||||||
|
"""Precipitation intensity.
|
||||||
|
|
||||||
|
Unit of measurement: UnitOfVolumetricFlux
|
||||||
|
- SI /metric: `mm/d`, `mm/h`
|
||||||
|
- USCS / imperial: `in/d`, `in/h`
|
||||||
|
"""
|
||||||
|
|
||||||
|
PRESSURE = "pressure"
|
||||||
|
"""Pressure.
|
||||||
|
|
||||||
|
Unit of measurement:
|
||||||
|
- `mbar`, `cbar`, `bar`
|
||||||
|
- `Pa`, `hPa`, `kPa`
|
||||||
|
- `inHg`
|
||||||
|
- `psi`
|
||||||
|
"""
|
||||||
|
|
||||||
|
REACTIVE_POWER = "reactive_power"
|
||||||
|
"""Reactive power.
|
||||||
|
|
||||||
|
Unit of measurement: `var`
|
||||||
|
"""
|
||||||
|
|
||||||
|
SIGNAL_STRENGTH = "signal_strength"
|
||||||
|
"""Signal strength.
|
||||||
|
|
||||||
|
Unit of measurement: `dB`, `dBm`
|
||||||
|
"""
|
||||||
|
|
||||||
|
SPEED = "speed"
|
||||||
|
"""Generic speed.
|
||||||
|
|
||||||
|
Unit of measurement: `SPEED_*` units or `UnitOfVolumetricFlux`
|
||||||
|
- SI /metric: `mm/d`, `mm/h`, `m/s`, `km/h`
|
||||||
|
- USCS / imperial: `in/d`, `in/h`, `ft/s`, `mph`
|
||||||
|
- Nautical: `kn`
|
||||||
|
"""
|
||||||
|
|
||||||
|
SULPHUR_DIOXIDE = "sulphur_dioxide"
|
||||||
|
"""Amount of SO2.
|
||||||
|
|
||||||
|
Unit of measurement: `µg/m³`
|
||||||
|
"""
|
||||||
|
|
||||||
TEMPERATURE = "temperature"
|
TEMPERATURE = "temperature"
|
||||||
|
"""Temperature.
|
||||||
|
|
||||||
|
Unit of measurement: `°C`, `°F`
|
||||||
|
"""
|
||||||
|
|
||||||
|
VOLATILE_ORGANIC_COMPOUNDS = "volatile_organic_compounds"
|
||||||
|
"""Amount of VOC.
|
||||||
|
|
||||||
|
Unit of measurement: `µg/m³`
|
||||||
|
"""
|
||||||
|
|
||||||
|
VOLTAGE = "voltage"
|
||||||
|
"""Voltage.
|
||||||
|
|
||||||
|
Unit of measurement: `V`
|
||||||
|
"""
|
||||||
|
|
||||||
|
VOLUME = "volume"
|
||||||
|
"""Generic volume.
|
||||||
|
|
||||||
|
Unit of measurement: `VOLUME_*` units
|
||||||
|
- SI / metric: `mL`, `L`, `m³`
|
||||||
|
- USCS / imperial: `fl. oz.`, `ft³`, `gal` (warning: volumes expressed in
|
||||||
|
USCS/imperial units are currently assumed to be US volumes)
|
||||||
|
"""
|
||||||
|
|
||||||
|
WATER = "water"
|
||||||
|
"""Water.
|
||||||
|
|
||||||
|
Unit of measurement:
|
||||||
|
- SI / metric: `m³`, `L`
|
||||||
|
- USCS / imperial: `ft³`, `gal` (warning: volumes expressed in
|
||||||
|
USCS/imperial units are currently assumed to be US volumes)
|
||||||
|
"""
|
||||||
|
|
||||||
|
WEIGHT = "weight"
|
||||||
|
"""Generic weight, represents a measurement of an object's mass.
|
||||||
|
|
||||||
|
Weight is used instead of mass to fit with every day language.
|
||||||
|
|
||||||
|
Unit of measurement: `MASS_*` units
|
||||||
|
- SI / metric: `µg`, `mg`, `g`, `kg`
|
||||||
|
- USCS / imperial: `oz`, `lb`
|
||||||
|
"""
|
||||||
|
|
||||||
|
WIND_SPEED = "wind_speed"
|
||||||
|
"""Wind speed.
|
||||||
|
|
||||||
|
Unit of measurement: `SPEED_*` units
|
||||||
|
- SI /metric: `m/s`, `km/h`
|
||||||
|
- USCS / imperial: `ft/s`, `mph`
|
||||||
|
- Nautical: `kn`
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
DEVICE_CLASSES_SCHEMA: Final = vol.All(vol.Lower, vol.Coerce(NumberDeviceClass))
|
DEVICE_CLASSES_SCHEMA: Final = vol.All(vol.Lower, vol.Coerce(NumberDeviceClass))
|
||||||
|
|
|
@ -88,6 +88,30 @@ SCAN_INTERVAL: Final = timedelta(seconds=30)
|
||||||
class SensorDeviceClass(StrEnum):
|
class SensorDeviceClass(StrEnum):
|
||||||
"""Device class for sensors."""
|
"""Device class for sensors."""
|
||||||
|
|
||||||
|
# Non-numerical device classes
|
||||||
|
DATE = "date"
|
||||||
|
"""Date.
|
||||||
|
|
||||||
|
Unit of measurement: `None`
|
||||||
|
|
||||||
|
ISO8601 format: https://en.wikipedia.org/wiki/ISO_8601
|
||||||
|
"""
|
||||||
|
|
||||||
|
DURATION = "duration"
|
||||||
|
"""Fixed duration.
|
||||||
|
|
||||||
|
Unit of measurement: `d`, `h`, `min`, `s`
|
||||||
|
"""
|
||||||
|
|
||||||
|
TIMESTAMP = "timestamp"
|
||||||
|
"""Timestamp.
|
||||||
|
|
||||||
|
Unit of measurement: `None`
|
||||||
|
|
||||||
|
ISO8601 format: https://en.wikipedia.org/wiki/ISO_8601
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Numerical device classes, these should be aligned with NumberDeviceClass
|
||||||
APPARENT_POWER = "apparent_power"
|
APPARENT_POWER = "apparent_power"
|
||||||
"""Apparent power.
|
"""Apparent power.
|
||||||
|
|
||||||
|
@ -124,14 +148,6 @@ class SensorDeviceClass(StrEnum):
|
||||||
Unit of measurement: `A`
|
Unit of measurement: `A`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DATE = "date"
|
|
||||||
"""Date.
|
|
||||||
|
|
||||||
Unit of measurement: `None`
|
|
||||||
|
|
||||||
ISO8601 format: https://en.wikipedia.org/wiki/ISO_8601
|
|
||||||
"""
|
|
||||||
|
|
||||||
DISTANCE = "distance"
|
DISTANCE = "distance"
|
||||||
"""Generic distance.
|
"""Generic distance.
|
||||||
|
|
||||||
|
@ -140,12 +156,6 @@ class SensorDeviceClass(StrEnum):
|
||||||
- USCS / imperial: `in`, `ft`, `yd`, `mi`
|
- USCS / imperial: `in`, `ft`, `yd`, `mi`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DURATION = "duration"
|
|
||||||
"""Fixed duration.
|
|
||||||
|
|
||||||
Unit of measurement: `d`, `h`, `min`, `s`
|
|
||||||
"""
|
|
||||||
|
|
||||||
ENERGY = "energy"
|
ENERGY = "energy"
|
||||||
"""Energy.
|
"""Energy.
|
||||||
|
|
||||||
|
@ -295,14 +305,6 @@ class SensorDeviceClass(StrEnum):
|
||||||
Unit of measurement: `°C`, `°F`
|
Unit of measurement: `°C`, `°F`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
TIMESTAMP = "timestamp"
|
|
||||||
"""Timestamp.
|
|
||||||
|
|
||||||
Unit of measurement: `None`
|
|
||||||
|
|
||||||
ISO8601 format: https://en.wikipedia.org/wiki/ISO_8601
|
|
||||||
"""
|
|
||||||
|
|
||||||
VOLATILE_ORGANIC_COMPOUNDS = "volatile_organic_compounds"
|
VOLATILE_ORGANIC_COMPOUNDS = "volatile_organic_compounds"
|
||||||
"""Amount of VOC.
|
"""Amount of VOC.
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ from homeassistant.components.number import (
|
||||||
NumberEntity,
|
NumberEntity,
|
||||||
NumberEntityDescription,
|
NumberEntityDescription,
|
||||||
)
|
)
|
||||||
|
from homeassistant.components.sensor import SensorDeviceClass
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID,
|
ATTR_ENTITY_ID,
|
||||||
ATTR_UNIT_OF_MEASUREMENT,
|
ATTR_UNIT_OF_MEASUREMENT,
|
||||||
|
@ -848,3 +849,20 @@ async def test_custom_unit_change(
|
||||||
state = hass.states.get(entity0.entity_id)
|
state = hass.states.get(entity0.entity_id)
|
||||||
assert float(state.state) == pytest.approx(float(default_value))
|
assert float(state.state) == pytest.approx(float(default_value))
|
||||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == default_unit
|
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == default_unit
|
||||||
|
|
||||||
|
|
||||||
|
def test_device_classes_aligned():
|
||||||
|
"""Make sure all sensor device classes are also available in NumberDeviceClass."""
|
||||||
|
|
||||||
|
non_numeric_device_classes = {
|
||||||
|
SensorDeviceClass.DATE,
|
||||||
|
SensorDeviceClass.DURATION,
|
||||||
|
SensorDeviceClass.TIMESTAMP,
|
||||||
|
}
|
||||||
|
|
||||||
|
for device_class in SensorDeviceClass:
|
||||||
|
if device_class in non_numeric_device_classes:
|
||||||
|
continue
|
||||||
|
|
||||||
|
assert hasattr(NumberDeviceClass, device_class.name)
|
||||||
|
assert getattr(NumberDeviceClass, device_class.name).value == device_class.value
|
||||||
|
|
|
@ -5,6 +5,7 @@ from decimal import Decimal
|
||||||
import pytest
|
import pytest
|
||||||
from pytest import approx
|
from pytest import approx
|
||||||
|
|
||||||
|
from homeassistant.components.number import NumberDeviceClass
|
||||||
from homeassistant.components.sensor import SensorDeviceClass
|
from homeassistant.components.sensor import SensorDeviceClass
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_UNIT_OF_MEASUREMENT,
|
ATTR_UNIT_OF_MEASUREMENT,
|
||||||
|
@ -927,3 +928,11 @@ async def test_unit_conversion_priority_legacy_conversion_removed(
|
||||||
state = hass.states.get(entity0.entity_id)
|
state = hass.states.get(entity0.entity_id)
|
||||||
assert float(state.state) == approx(float(original_value))
|
assert float(state.state) == approx(float(original_value))
|
||||||
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == original_unit
|
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == original_unit
|
||||||
|
|
||||||
|
|
||||||
|
def test_device_classes_aligned():
|
||||||
|
"""Make sure all number device classes are also available in SensorDeviceClass."""
|
||||||
|
|
||||||
|
for device_class in NumberDeviceClass:
|
||||||
|
assert hasattr(SensorDeviceClass, device_class.name)
|
||||||
|
assert getattr(SensorDeviceClass, device_class.name).value == device_class.value
|
||||||
|
|
Loading…
Reference in New Issue