Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move pressure utility to unit_conversion #78953

Merged
merged 1 commit into from Sep 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 6 additions & 7 deletions homeassistant/components/recorder/statistics.py
Expand Up @@ -32,7 +32,6 @@
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,
)
Expand Down Expand Up @@ -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:
Expand All @@ -178,17 +177,17 @@ 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",
}

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,
}
Expand All @@ -200,7 +199,7 @@ def _convert_volume_to_m3(from_unit: str, value: float) -> float:
] = {
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,
}
Expand Down
12 changes: 6 additions & 6 deletions homeassistant/components/recorder/websocket_api.py
Expand Up @@ -19,12 +19,12 @@
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 (
Expand Down Expand Up @@ -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),
}
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/sensor/__init__.py
Expand Up @@ -57,7 +57,7 @@
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,
Expand Down Expand Up @@ -214,7 +214,7 @@ class SensorStateClass(StrEnum):
}

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,
Expand Down
17 changes: 8 additions & 9 deletions homeassistant/components/sensor/recorder.py
Expand Up @@ -49,7 +49,6 @@
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,
)
Expand Down Expand Up @@ -105,15 +104,15 @@
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
Expand Down
46 changes: 6 additions & 40 deletions homeassistant/util/pressure.py
@@ -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,
Expand All @@ -17,45 +15,13 @@
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,
)

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,
}
from .unit_conversion import PressureConverter

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)
51 changes: 38 additions & 13 deletions homeassistant/util/unit_conversion.py
Expand Up @@ -10,17 +10,21 @@
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:
Expand All @@ -34,19 +38,19 @@ class BaseUnitConverter:
class BaseUnitConverterWithUnitConversion(BaseUnitConverter):
"""Define the format of a conversion utility."""

DEVICE_CLASS: str
UNIT_CLASS: str
UNIT_CONVERSION: dict[str, float]

@classmethod
def convert(cls, value: float, from_unit: str, to_unit: str) -> float:
"""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):
Expand All @@ -62,7 +66,7 @@ def convert(cls, value: float, from_unit: str, to_unit: str) -> float:
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,
Expand All @@ -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,
Expand All @@ -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):
Expand Down