From fca5cc6ea3c3e96fa4224eb73821fe6695c33177 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 1 Mar 2023 11:22:57 +0100 Subject: [PATCH] Add number + sensor device class volume storage (#88312) * Add number + sensor device class volume storage * Fix typo * Format code * Update device automations --- homeassistant/components/number/const.py | 13 +++++++++++++ homeassistant/components/sensor/const.py | 14 ++++++++++++++ .../components/sensor/device_condition.py | 1 + homeassistant/components/sensor/device_trigger.py | 1 + tests/components/sensor/test_device_condition.py | 2 ++ tests/components/sensor/test_device_trigger.py | 2 ++ 6 files changed, 33 insertions(+) diff --git a/homeassistant/components/number/const.py b/homeassistant/components/number/const.py index aa57bb2b716..48cd04dc26e 100644 --- a/homeassistant/components/number/const.py +++ b/homeassistant/components/number/const.py @@ -324,6 +324,18 @@ class NumberDeviceClass(StrEnum): USCS/imperial units are currently assumed to be US volumes) """ + VOLUME_STORAGE = "volume_storage" + """Generic stored volume. + + Use this device class for sensors measuring stored volume, for example the amount + of fuel in a fuel tank. + + Unit of measurement: `VOLUME_*` units + - SI / metric: `mL`, `L`, `m³` + - USCS / imperial: `ft³`, `CCF`, `fl. oz.`, `gal` (warning: volumes expressed in + USCS/imperial units are currently assumed to be US volumes) + """ + WATER = "water" """Water. @@ -411,6 +423,7 @@ DEVICE_CLASS_UNITS: dict[NumberDeviceClass, set[type[StrEnum] | str | None]] = { }, NumberDeviceClass.VOLTAGE: set(UnitOfElectricPotential), NumberDeviceClass.VOLUME: set(UnitOfVolume), + NumberDeviceClass.VOLUME_STORAGE: set(UnitOfVolume), NumberDeviceClass.WATER: { UnitOfVolume.CENTUM_CUBIC_FEET, UnitOfVolume.CUBIC_FEET, diff --git a/homeassistant/components/sensor/const.py b/homeassistant/components/sensor/const.py index 8ded1c304da..356eb68b4db 100644 --- a/homeassistant/components/sensor/const.py +++ b/homeassistant/components/sensor/const.py @@ -362,6 +362,18 @@ class SensorDeviceClass(StrEnum): USCS/imperial units are currently assumed to be US volumes) """ + VOLUME_STORAGE = "volume_storage" + """Generic stored volume. + + Use this device class for sensors measuring stored volume, for example the amount + of fuel in a fuel tank. + + Unit of measurement: `VOLUME_*` units + - SI / metric: `mL`, `L`, `m³` + - USCS / imperial: `ft³`, `CCF`, `fl. oz.`, `gal` (warning: volumes expressed in + USCS/imperial units are currently assumed to be US volumes) + """ + WATER = "water" """Water. @@ -451,6 +463,7 @@ UNIT_CONVERTERS: dict[SensorDeviceClass | str | None, type[BaseUnitConverter]] = SensorDeviceClass.TEMPERATURE: TemperatureConverter, SensorDeviceClass.VOLTAGE: ElectricPotentialConverter, SensorDeviceClass.VOLUME: VolumeConverter, + SensorDeviceClass.VOLUME_STORAGE: VolumeConverter, SensorDeviceClass.WATER: VolumeConverter, SensorDeviceClass.WEIGHT: MassConverter, SensorDeviceClass.WIND_SPEED: SpeedConverter, @@ -573,6 +586,7 @@ DEVICE_CLASS_STATE_CLASSES: dict[SensorDeviceClass, set[SensorStateClass]] = { SensorStateClass.TOTAL, SensorStateClass.TOTAL_INCREASING, }, + SensorDeviceClass.VOLUME_STORAGE: {SensorStateClass.MEASUREMENT}, SensorDeviceClass.WATER: { SensorStateClass.TOTAL, SensorStateClass.TOTAL_INCREASING, diff --git a/homeassistant/components/sensor/device_condition.py b/homeassistant/components/sensor/device_condition.py index 6ed47cbf63e..8547827d748 100644 --- a/homeassistant/components/sensor/device_condition.py +++ b/homeassistant/components/sensor/device_condition.py @@ -122,6 +122,7 @@ ENTITY_CONDITIONS = { ], SensorDeviceClass.VOLTAGE: [{CONF_TYPE: CONF_IS_VOLTAGE}], SensorDeviceClass.VOLUME: [{CONF_TYPE: CONF_IS_VOLUME}], + SensorDeviceClass.VOLUME_STORAGE: [{CONF_TYPE: CONF_IS_VOLUME}], SensorDeviceClass.WATER: [{CONF_TYPE: CONF_IS_WATER}], SensorDeviceClass.WEIGHT: [{CONF_TYPE: CONF_IS_WEIGHT}], SensorDeviceClass.WIND_SPEED: [{CONF_TYPE: CONF_IS_WIND_SPEED}], diff --git a/homeassistant/components/sensor/device_trigger.py b/homeassistant/components/sensor/device_trigger.py index 7e498321b3e..3b2a0485554 100644 --- a/homeassistant/components/sensor/device_trigger.py +++ b/homeassistant/components/sensor/device_trigger.py @@ -121,6 +121,7 @@ ENTITY_TRIGGERS = { ], SensorDeviceClass.VOLTAGE: [{CONF_TYPE: CONF_VOLTAGE}], SensorDeviceClass.VOLUME: [{CONF_TYPE: CONF_VOLUME}], + SensorDeviceClass.VOLUME_STORAGE: [{CONF_TYPE: CONF_VOLUME}], SensorDeviceClass.WATER: [{CONF_TYPE: CONF_WATER}], SensorDeviceClass.WEIGHT: [{CONF_TYPE: CONF_WEIGHT}], SensorDeviceClass.WIND_SPEED: [{CONF_TYPE: CONF_WIND_SPEED}], diff --git a/tests/components/sensor/test_device_condition.py b/tests/components/sensor/test_device_condition.py index 24d480e24b3..5e93bf2a64c 100644 --- a/tests/components/sensor/test_device_condition.py +++ b/tests/components/sensor/test_device_condition.py @@ -52,6 +52,7 @@ def test_matches_device_classes(device_class: SensorDeviceClass) -> None: SensorDeviceClass.CO: "CONF_IS_CO", SensorDeviceClass.CO2: "CONF_IS_CO2", SensorDeviceClass.ENERGY_STORAGE: "CONF_IS_ENERGY", + SensorDeviceClass.VOLUME_STORAGE: "CONF_IS_VOLUME", }.get(device_class, f"CONF_IS_{device_class.value.upper()}") assert hasattr(device_condition, constant_name), f"Missing constant {constant_name}" @@ -59,6 +60,7 @@ def test_matches_device_classes(device_class: SensorDeviceClass) -> None: constant_value = { SensorDeviceClass.BATTERY: "is_battery_level", SensorDeviceClass.ENERGY_STORAGE: "is_energy", + SensorDeviceClass.VOLUME_STORAGE: "is_volume", }.get(device_class, f"is_{device_class.value}") assert getattr(device_condition, constant_name) == constant_value diff --git a/tests/components/sensor/test_device_trigger.py b/tests/components/sensor/test_device_trigger.py index 34b5d6fb40f..37f44a5b40d 100644 --- a/tests/components/sensor/test_device_trigger.py +++ b/tests/components/sensor/test_device_trigger.py @@ -56,6 +56,7 @@ def test_matches_device_classes(device_class: SensorDeviceClass) -> None: SensorDeviceClass.CO: "CONF_CO", SensorDeviceClass.CO2: "CONF_CO2", SensorDeviceClass.ENERGY_STORAGE: "CONF_ENERGY", + SensorDeviceClass.VOLUME_STORAGE: "CONF_VOLUME", }.get(device_class, f"CONF_{device_class.value.upper()}") assert hasattr(device_trigger, constant_name), f"Missing constant {constant_name}" @@ -63,6 +64,7 @@ def test_matches_device_classes(device_class: SensorDeviceClass) -> None: constant_value = { SensorDeviceClass.BATTERY: "battery_level", SensorDeviceClass.ENERGY_STORAGE: "energy", + SensorDeviceClass.VOLUME_STORAGE: "volume", }.get(device_class, device_class.value) assert getattr(device_trigger, constant_name) == constant_value