1
mirror of https://github.com/home-assistant/core synced 2024-10-04 07:58:43 +02:00

Move pressure utility to unit_conversion (#78953)

This commit is contained in:
epenet 2022-09-22 16:44:09 +02:00 committed by GitHub
parent 0767cdd935
commit 523d8d246b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 268 additions and 78 deletions

View File

@ -32,7 +32,6 @@ from homeassistant.helpers.storage import STORAGE_DIR
from homeassistant.helpers.typing import UNDEFINED, UndefinedType
from homeassistant.util import (
dt as dt_util,
pressure as pressure_util,
temperature as temperature_util,
volume as volume_util,
)
@ -155,7 +154,7 @@ def _convert_pressure_from_pa(to_unit: str, value: float | None) -> float | None
"""Convert pressure in Pa to to_unit."""
if value is None:
return None
return pressure_util.convert(value, pressure_util.NORMALIZED_UNIT, to_unit)
return PressureConverter.convert(value, PressureConverter.NORMALIZED_UNIT, to_unit)
def _convert_temperature_from_c(to_unit: str, value: float | None) -> float | None:
@ -178,9 +177,9 @@ def _convert_volume_to_m3(from_unit: str, value: float) -> float:
STATISTIC_UNIT_TO_UNIT_CLASS: dict[str | None, str] = {
EnergyConverter.NORMALIZED_UNIT: "energy",
PowerConverter.NORMALIZED_UNIT: "power",
pressure_util.NORMALIZED_UNIT: "pressure",
EnergyConverter.NORMALIZED_UNIT: EnergyConverter.UNIT_CLASS,
PowerConverter.NORMALIZED_UNIT: PowerConverter.UNIT_CLASS,
PressureConverter.NORMALIZED_UNIT: PressureConverter.UNIT_CLASS,
temperature_util.NORMALIZED_UNIT: "temperature",
volume_util.NORMALIZED_UNIT: "volume",
}
@ -188,7 +187,7 @@ STATISTIC_UNIT_TO_UNIT_CLASS: dict[str | None, str] = {
STATISTIC_UNIT_TO_UNIT_CONVERTER: dict[str | None, type[BaseUnitConverter]] = {
EnergyConverter.NORMALIZED_UNIT: EnergyConverter,
PowerConverter.NORMALIZED_UNIT: PowerConverter,
pressure_util.NORMALIZED_UNIT: PressureConverter,
PressureConverter.NORMALIZED_UNIT: PressureConverter,
temperature_util.NORMALIZED_UNIT: TemperatureConverter,
volume_util.NORMALIZED_UNIT: VolumeConverter,
}
@ -200,7 +199,7 @@ STATISTIC_UNIT_TO_DISPLAY_UNIT_FUNCTIONS: dict[
] = {
EnergyConverter.NORMALIZED_UNIT: _convert_energy_from_kwh,
PowerConverter.NORMALIZED_UNIT: _convert_power_from_w,
pressure_util.NORMALIZED_UNIT: _convert_pressure_from_pa,
PressureConverter.NORMALIZED_UNIT: _convert_pressure_from_pa,
temperature_util.NORMALIZED_UNIT: _convert_temperature_from_c,
volume_util.NORMALIZED_UNIT: _convert_volume_from_m3,
}

View File

@ -19,12 +19,12 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant, callback, valid_entity_id
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.json import JSON_DUMP
from homeassistant.util import (
dt as dt_util,
pressure as pressure_util,
temperature as temperature_util,
from homeassistant.util import dt as dt_util, temperature as temperature_util
from homeassistant.util.unit_conversion import (
EnergyConverter,
PowerConverter,
PressureConverter,
)
from homeassistant.util.unit_conversion import EnergyConverter, PowerConverter
from .const import MAX_QUEUE_BACKLOG
from .statistics import (
@ -122,7 +122,7 @@ async def ws_handle_get_statistics_during_period(
{
vol.Optional("energy"): vol.In(EnergyConverter.VALID_UNITS),
vol.Optional("power"): vol.In(PowerConverter.VALID_UNITS),
vol.Optional("pressure"): vol.In(pressure_util.VALID_UNITS),
vol.Optional("pressure"): vol.In(PressureConverter.VALID_UNITS),
vol.Optional("temperature"): vol.In(temperature_util.VALID_UNITS),
vol.Optional("volume"): vol.Any(VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS),
}

View File

@ -57,7 +57,7 @@ from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.restore_state import ExtraStoredData, RestoreEntity
from homeassistant.helpers.typing import ConfigType, StateType
from homeassistant.util import dt as dt_util, pressure as pressure_util
from homeassistant.util import dt as dt_util
from homeassistant.util.unit_conversion import (
BaseUnitConverter,
PressureConverter,
@ -214,7 +214,7 @@ UNIT_CONVERTERS: dict[str, type[BaseUnitConverter]] = {
}
UNIT_RATIOS: dict[str, dict[str, float]] = {
SensorDeviceClass.PRESSURE: pressure_util.UNIT_CONVERSION,
SensorDeviceClass.PRESSURE: PressureConverter.UNIT_CONVERSION,
SensorDeviceClass.TEMPERATURE: {
TEMP_CELSIUS: 1.0,
TEMP_FAHRENHEIT: 1.8,

View File

@ -49,7 +49,6 @@ from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity import entity_sources
from homeassistant.util import (
dt as dt_util,
pressure as pressure_util,
temperature as temperature_util,
volume as volume_util,
)
@ -105,15 +104,15 @@ UNIT_CONVERSIONS: dict[str, dict[str, Callable]] = {
POWER_KILO_WATT: lambda x: x / PowerConverter.UNIT_CONVERSION[POWER_KILO_WATT],
},
# Convert pressure to Pa
# Note: pressure_util.convert is bypassed to avoid redundant error checking
# Note: PressureConverter.convert is bypassed to avoid redundant error checking
SensorDeviceClass.PRESSURE: {
PRESSURE_BAR: lambda x: x / pressure_util.UNIT_CONVERSION[PRESSURE_BAR],
PRESSURE_HPA: lambda x: x / pressure_util.UNIT_CONVERSION[PRESSURE_HPA],
PRESSURE_INHG: lambda x: x / pressure_util.UNIT_CONVERSION[PRESSURE_INHG],
PRESSURE_KPA: lambda x: x / pressure_util.UNIT_CONVERSION[PRESSURE_KPA],
PRESSURE_MBAR: lambda x: x / pressure_util.UNIT_CONVERSION[PRESSURE_MBAR],
PRESSURE_PA: lambda x: x / pressure_util.UNIT_CONVERSION[PRESSURE_PA],
PRESSURE_PSI: lambda x: x / pressure_util.UNIT_CONVERSION[PRESSURE_PSI],
PRESSURE_BAR: lambda x: x / PressureConverter.UNIT_CONVERSION[PRESSURE_BAR],
PRESSURE_HPA: lambda x: x / PressureConverter.UNIT_CONVERSION[PRESSURE_HPA],
PRESSURE_INHG: lambda x: x / PressureConverter.UNIT_CONVERSION[PRESSURE_INHG],
PRESSURE_KPA: lambda x: x / PressureConverter.UNIT_CONVERSION[PRESSURE_KPA],
PRESSURE_MBAR: lambda x: x / PressureConverter.UNIT_CONVERSION[PRESSURE_MBAR],
PRESSURE_PA: lambda x: x / PressureConverter.UNIT_CONVERSION[PRESSURE_PA],
PRESSURE_PSI: lambda x: x / PressureConverter.UNIT_CONVERSION[PRESSURE_PSI],
},
# Convert temperature to °C
# Note: temperature_util.convert is bypassed to avoid redundant error checking

View File

@ -1,9 +1,7 @@
"""Pressure util functions."""
from __future__ import annotations
from numbers import Number
from homeassistant.const import (
from homeassistant.const import ( # pylint: disable=unused-import # noqa: F401
PRESSURE,
PRESSURE_BAR,
PRESSURE_CBAR,
@ -17,45 +15,13 @@ from homeassistant.const import (
UNIT_NOT_RECOGNIZED_TEMPLATE,
)
VALID_UNITS: tuple[str, ...] = (
PRESSURE_PA,
PRESSURE_HPA,
PRESSURE_KPA,
PRESSURE_BAR,
PRESSURE_CBAR,
PRESSURE_MBAR,
PRESSURE_INHG,
PRESSURE_PSI,
PRESSURE_MMHG,
)
from .unit_conversion import PressureConverter
UNIT_CONVERSION: dict[str, float] = {
PRESSURE_PA: 1,
PRESSURE_HPA: 1 / 100,
PRESSURE_KPA: 1 / 1000,
PRESSURE_BAR: 1 / 100000,
PRESSURE_CBAR: 1 / 1000,
PRESSURE_MBAR: 1 / 100,
PRESSURE_INHG: 1 / 3386.389,
PRESSURE_PSI: 1 / 6894.757,
PRESSURE_MMHG: 1 / 133.322,
}
NORMALIZED_UNIT = PRESSURE_PA
UNIT_CONVERSION: dict[str, float] = PressureConverter.UNIT_CONVERSION
VALID_UNITS: tuple[str, ...] = PressureConverter.VALID_UNITS
def convert(value: float, from_unit: str, to_unit: str) -> float:
"""Convert one unit of measurement to another."""
if from_unit not in VALID_UNITS:
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(from_unit, PRESSURE))
if to_unit not in VALID_UNITS:
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(to_unit, PRESSURE))
if not isinstance(value, Number):
raise TypeError(f"{value} is not of numeric type")
if from_unit == to_unit:
return value
pascals = value / UNIT_CONVERSION[from_unit]
return pascals * UNIT_CONVERSION[to_unit]
# Need to add warning when core migration finished
return PressureConverter.convert(value, from_unit, to_unit)

View File

@ -10,17 +10,21 @@ from homeassistant.const import (
ENERGY_WATT_HOUR,
POWER_KILO_WATT,
POWER_WATT,
PRESSURE_BAR,
PRESSURE_CBAR,
PRESSURE_HPA,
PRESSURE_INHG,
PRESSURE_KPA,
PRESSURE_MBAR,
PRESSURE_MMHG,
PRESSURE_PA,
PRESSURE_PSI,
TEMP_CELSIUS,
UNIT_NOT_RECOGNIZED_TEMPLATE,
VOLUME_CUBIC_METERS,
)
from . import (
pressure as pressure_util,
temperature as temperature_util,
volume as volume_util,
)
from . import temperature as temperature_util, volume as volume_util
class BaseUnitConverter:
@ -34,7 +38,7 @@ class BaseUnitConverter:
class BaseUnitConverterWithUnitConversion(BaseUnitConverter):
"""Define the format of a conversion utility."""
DEVICE_CLASS: str
UNIT_CLASS: str
UNIT_CONVERSION: dict[str, float]
@classmethod
@ -42,11 +46,11 @@ class BaseUnitConverterWithUnitConversion(BaseUnitConverter):
"""Convert one unit of measurement to another."""
if from_unit not in cls.VALID_UNITS:
raise ValueError(
UNIT_NOT_RECOGNIZED_TEMPLATE.format(from_unit, cls.DEVICE_CLASS)
UNIT_NOT_RECOGNIZED_TEMPLATE.format(from_unit, cls.UNIT_CLASS)
)
if to_unit not in cls.VALID_UNITS:
raise ValueError(
UNIT_NOT_RECOGNIZED_TEMPLATE.format(to_unit, cls.DEVICE_CLASS)
UNIT_NOT_RECOGNIZED_TEMPLATE.format(to_unit, cls.UNIT_CLASS)
)
if not isinstance(value, Number):
@ -62,7 +66,7 @@ class BaseUnitConverterWithUnitConversion(BaseUnitConverter):
class EnergyConverter(BaseUnitConverterWithUnitConversion):
"""Utility to convert energy values."""
DEVICE_CLASS = "energy"
UNIT_CLASS = "energy"
NORMALIZED_UNIT = ENERGY_KILO_WATT_HOUR
UNIT_CONVERSION: dict[str, float] = {
ENERGY_WATT_HOUR: 1 * 1000,
@ -79,7 +83,7 @@ class EnergyConverter(BaseUnitConverterWithUnitConversion):
class PowerConverter(BaseUnitConverterWithUnitConversion):
"""Utility to convert power values."""
DEVICE_CLASS = "power"
UNIT_CLASS = "power"
NORMALIZED_UNIT = POWER_WATT
UNIT_CONVERSION: dict[str, float] = {
POWER_WATT: 1,
@ -91,12 +95,33 @@ class PowerConverter(BaseUnitConverterWithUnitConversion):
)
class PressureConverter(BaseUnitConverter):
class PressureConverter(BaseUnitConverterWithUnitConversion):
"""Utility to convert pressure values."""
UNIT_CLASS = "pressure"
NORMALIZED_UNIT = PRESSURE_PA
VALID_UNITS = pressure_util.VALID_UNITS
convert = pressure_util.convert
UNIT_CONVERSION: dict[str, float] = {
PRESSURE_PA: 1,
PRESSURE_HPA: 1 / 100,
PRESSURE_KPA: 1 / 1000,
PRESSURE_BAR: 1 / 100000,
PRESSURE_CBAR: 1 / 1000,
PRESSURE_MBAR: 1 / 100,
PRESSURE_INHG: 1 / 3386.389,
PRESSURE_PSI: 1 / 6894.757,
PRESSURE_MMHG: 1 / 133.322,
}
VALID_UNITS: tuple[str, ...] = (
PRESSURE_PA,
PRESSURE_HPA,
PRESSURE_KPA,
PRESSURE_BAR,
PRESSURE_CBAR,
PRESSURE_MBAR,
PRESSURE_INHG,
PRESSURE_PSI,
PRESSURE_MMHG,
)
class TemperatureConverter(BaseUnitConverter):

View File

@ -7,11 +7,20 @@ from homeassistant.const import (
ENERGY_WATT_HOUR,
POWER_KILO_WATT,
POWER_WATT,
PRESSURE_CBAR,
PRESSURE_HPA,
PRESSURE_INHG,
PRESSURE_KPA,
PRESSURE_MBAR,
PRESSURE_MMHG,
PRESSURE_PA,
PRESSURE_PSI,
)
from homeassistant.util.unit_conversion import (
BaseUnitConverter,
EnergyConverter,
PowerConverter,
PressureConverter,
)
INVALID_SYMBOL = "bob"
@ -25,6 +34,14 @@ INVALID_SYMBOL = "bob"
(EnergyConverter, ENERGY_MEGA_WATT_HOUR),
(PowerConverter, POWER_WATT),
(PowerConverter, POWER_KILO_WATT),
(PressureConverter, PRESSURE_PA),
(PressureConverter, PRESSURE_HPA),
(PressureConverter, PRESSURE_MBAR),
(PressureConverter, PRESSURE_INHG),
(PressureConverter, PRESSURE_KPA),
(PressureConverter, PRESSURE_CBAR),
(PressureConverter, PRESSURE_MMHG),
(PressureConverter, PRESSURE_PSI),
],
)
def test_convert_same_unit(converter: type[BaseUnitConverter], valid_unit: str) -> None:
@ -37,6 +54,7 @@ def test_convert_same_unit(converter: type[BaseUnitConverter], valid_unit: str)
[
(EnergyConverter, ENERGY_KILO_WATT_HOUR),
(PowerConverter, POWER_WATT),
(PressureConverter, PRESSURE_PA),
],
)
def test_convert_invalid_unit(
@ -47,7 +65,7 @@ def test_convert_invalid_unit(
converter.convert(5, INVALID_SYMBOL, valid_unit)
with pytest.raises(ValueError):
EnergyConverter.convert(5, valid_unit, INVALID_SYMBOL)
converter.convert(5, valid_unit, INVALID_SYMBOL)
@pytest.mark.parametrize(
@ -55,6 +73,7 @@ def test_convert_invalid_unit(
[
(EnergyConverter, ENERGY_WATT_HOUR, ENERGY_KILO_WATT_HOUR),
(PowerConverter, POWER_WATT, POWER_KILO_WATT),
(PressureConverter, PRESSURE_HPA, PRESSURE_INHG),
],
)
def test_convert_nonnumeric_value(
@ -76,6 +95,188 @@ def test_convert_nonnumeric_value(
(EnergyConverter, 10, ENERGY_MEGA_WATT_HOUR, 10000, ENERGY_KILO_WATT_HOUR),
(PowerConverter, 10, POWER_KILO_WATT, 10000, POWER_WATT),
(PowerConverter, 10, POWER_WATT, 0.01, POWER_KILO_WATT),
(
PressureConverter,
1000,
PRESSURE_HPA,
pytest.approx(14.5037743897),
PRESSURE_PSI,
),
(
PressureConverter,
1000,
PRESSURE_HPA,
pytest.approx(29.5299801647),
PRESSURE_INHG,
),
(
PressureConverter,
1000,
PRESSURE_HPA,
pytest.approx(100000),
PRESSURE_PA,
),
(
PressureConverter,
1000,
PRESSURE_HPA,
pytest.approx(100),
PRESSURE_KPA,
),
(
PressureConverter,
1000,
PRESSURE_HPA,
pytest.approx(1000),
PRESSURE_MBAR,
),
(
PressureConverter,
1000,
PRESSURE_HPA,
pytest.approx(100),
PRESSURE_CBAR,
),
(
PressureConverter,
100,
PRESSURE_KPA,
pytest.approx(14.5037743897),
PRESSURE_PSI,
),
(
PressureConverter,
100,
PRESSURE_KPA,
pytest.approx(29.5299801647),
PRESSURE_INHG,
),
(
PressureConverter,
100,
PRESSURE_KPA,
pytest.approx(100000),
PRESSURE_PA,
),
(
PressureConverter,
100,
PRESSURE_KPA,
pytest.approx(1000),
PRESSURE_HPA,
),
(
PressureConverter,
100,
PRESSURE_KPA,
pytest.approx(1000),
PRESSURE_MBAR,
),
(
PressureConverter,
100,
PRESSURE_KPA,
pytest.approx(100),
PRESSURE_CBAR,
),
(
PressureConverter,
30,
PRESSURE_INHG,
pytest.approx(14.7346266155),
PRESSURE_PSI,
),
(
PressureConverter,
30,
PRESSURE_INHG,
pytest.approx(101.59167),
PRESSURE_KPA,
),
(
PressureConverter,
30,
PRESSURE_INHG,
pytest.approx(1015.9167),
PRESSURE_HPA,
),
(
PressureConverter,
30,
PRESSURE_INHG,
pytest.approx(101591.67),
PRESSURE_PA,
),
(
PressureConverter,
30,
PRESSURE_INHG,
pytest.approx(1015.9167),
PRESSURE_MBAR,
),
(
PressureConverter,
30,
PRESSURE_INHG,
pytest.approx(101.59167),
PRESSURE_CBAR,
),
(
PressureConverter,
30,
PRESSURE_INHG,
pytest.approx(762.002),
PRESSURE_MMHG,
),
(
PressureConverter,
30,
PRESSURE_MMHG,
pytest.approx(0.580102),
PRESSURE_PSI,
),
(
PressureConverter,
30,
PRESSURE_MMHG,
pytest.approx(3.99966),
PRESSURE_KPA,
),
(
PressureConverter,
30,
PRESSURE_MMHG,
pytest.approx(39.9966),
PRESSURE_HPA,
),
(
PressureConverter,
30,
PRESSURE_MMHG,
pytest.approx(3999.66),
PRESSURE_PA,
),
(
PressureConverter,
30,
PRESSURE_MMHG,
pytest.approx(39.9966),
PRESSURE_MBAR,
),
(
PressureConverter,
30,
PRESSURE_MMHG,
pytest.approx(3.99966),
PRESSURE_CBAR,
),
(
PressureConverter,
30,
PRESSURE_MMHG,
pytest.approx(1.181099),
PRESSURE_INHG,
),
],
)
def test_convert(