mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 15:17:35 +00:00
Cleanup unit conversion (#79197)
* Move UNIT_RATIO to BaseUnitConverter * Make UNIT_CONVERSION private * Remove STATISTIC_UNIT_TO_UNIT_CLASS constant * Cleanup websocket_api * Imrpove valid_units check
This commit is contained in:
parent
a5c9c1880a
commit
5438552d4a
@ -124,17 +124,6 @@ QUERY_STATISTIC_META = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
STATISTIC_UNIT_TO_UNIT_CLASS: dict[str | None, str] = {
|
|
||||||
DistanceConverter.NORMALIZED_UNIT: DistanceConverter.UNIT_CLASS,
|
|
||||||
EnergyConverter.NORMALIZED_UNIT: EnergyConverter.UNIT_CLASS,
|
|
||||||
MassConverter.NORMALIZED_UNIT: MassConverter.UNIT_CLASS,
|
|
||||||
PowerConverter.NORMALIZED_UNIT: PowerConverter.UNIT_CLASS,
|
|
||||||
PressureConverter.NORMALIZED_UNIT: PressureConverter.UNIT_CLASS,
|
|
||||||
SpeedConverter.NORMALIZED_UNIT: SpeedConverter.UNIT_CLASS,
|
|
||||||
TemperatureConverter.NORMALIZED_UNIT: TemperatureConverter.UNIT_CLASS,
|
|
||||||
VolumeConverter.NORMALIZED_UNIT: VolumeConverter.UNIT_CLASS,
|
|
||||||
}
|
|
||||||
|
|
||||||
STATISTIC_UNIT_TO_UNIT_CONVERTER: dict[str | None, type[BaseUnitConverter]] = {
|
STATISTIC_UNIT_TO_UNIT_CONVERTER: dict[str | None, type[BaseUnitConverter]] = {
|
||||||
DistanceConverter.NORMALIZED_UNIT: DistanceConverter,
|
DistanceConverter.NORMALIZED_UNIT: DistanceConverter,
|
||||||
EnergyConverter.NORMALIZED_UNIT: EnergyConverter,
|
EnergyConverter.NORMALIZED_UNIT: EnergyConverter,
|
||||||
@ -150,6 +139,13 @@ STATISTIC_UNIT_TO_UNIT_CONVERTER: dict[str | None, type[BaseUnitConverter]] = {
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_unit_class(unit: str | None) -> str | None:
|
||||||
|
"""Get corresponding unit class from from the normalized statistics unit."""
|
||||||
|
if converter := STATISTIC_UNIT_TO_UNIT_CONVERTER.get(unit):
|
||||||
|
return converter.UNIT_CLASS
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _get_statistic_to_display_unit_converter(
|
def _get_statistic_to_display_unit_converter(
|
||||||
statistic_unit: str | None,
|
statistic_unit: str | None,
|
||||||
state_unit: str | None,
|
state_unit: str | None,
|
||||||
@ -168,14 +164,13 @@ def _get_statistic_to_display_unit_converter(
|
|||||||
return no_conversion
|
return no_conversion
|
||||||
|
|
||||||
display_unit: str | None
|
display_unit: str | None
|
||||||
unit_class = STATISTIC_UNIT_TO_UNIT_CLASS[statistic_unit]
|
unit_class = converter.UNIT_CLASS
|
||||||
if requested_units and unit_class in requested_units:
|
if requested_units and unit_class in requested_units:
|
||||||
display_unit = requested_units[unit_class]
|
display_unit = requested_units[unit_class]
|
||||||
else:
|
else:
|
||||||
display_unit = state_unit
|
display_unit = state_unit
|
||||||
|
|
||||||
unit_converter = STATISTIC_UNIT_TO_UNIT_CONVERTER[statistic_unit]
|
if display_unit not in converter.VALID_UNITS:
|
||||||
if display_unit not in unit_converter.VALID_UNITS:
|
|
||||||
# Guard against invalid state unit in the DB
|
# Guard against invalid state unit in the DB
|
||||||
return no_conversion
|
return no_conversion
|
||||||
|
|
||||||
@ -909,9 +904,7 @@ def list_statistic_ids(
|
|||||||
"has_sum": meta["has_sum"],
|
"has_sum": meta["has_sum"],
|
||||||
"name": meta["name"],
|
"name": meta["name"],
|
||||||
"source": meta["source"],
|
"source": meta["source"],
|
||||||
"unit_class": STATISTIC_UNIT_TO_UNIT_CLASS.get(
|
"unit_class": _get_unit_class(meta["unit_of_measurement"]),
|
||||||
meta["unit_of_measurement"]
|
|
||||||
),
|
|
||||||
"unit_of_measurement": meta["unit_of_measurement"],
|
"unit_of_measurement": meta["unit_of_measurement"],
|
||||||
}
|
}
|
||||||
for _, meta in metadata.values()
|
for _, meta in metadata.values()
|
||||||
@ -934,9 +927,7 @@ def list_statistic_ids(
|
|||||||
"name": meta["name"],
|
"name": meta["name"],
|
||||||
"source": meta["source"],
|
"source": meta["source"],
|
||||||
"display_unit_of_measurement": meta["state_unit_of_measurement"],
|
"display_unit_of_measurement": meta["state_unit_of_measurement"],
|
||||||
"unit_class": STATISTIC_UNIT_TO_UNIT_CLASS.get(
|
"unit_class": _get_unit_class(meta["unit_of_measurement"]),
|
||||||
meta["unit_of_measurement"]
|
|
||||||
),
|
|
||||||
"unit_of_measurement": meta["unit_of_measurement"],
|
"unit_of_measurement": meta["unit_of_measurement"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,6 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant.components import websocket_api
|
from homeassistant.components import websocket_api
|
||||||
from homeassistant.components.websocket_api import messages
|
from homeassistant.components.websocket_api import messages
|
||||||
from homeassistant.const import (
|
|
||||||
ENERGY_KILO_WATT_HOUR,
|
|
||||||
ENERGY_MEGA_WATT_HOUR,
|
|
||||||
ENERGY_WATT_HOUR,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant, callback, valid_entity_id
|
from homeassistant.core import HomeAssistant, callback, valid_entity_id
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.json import JSON_DUMP
|
from homeassistant.helpers.json import JSON_DUMP
|
||||||
@ -31,6 +26,7 @@ from homeassistant.util.unit_conversion import (
|
|||||||
|
|
||||||
from .const import MAX_QUEUE_BACKLOG
|
from .const import MAX_QUEUE_BACKLOG
|
||||||
from .statistics import (
|
from .statistics import (
|
||||||
|
STATISTIC_UNIT_TO_UNIT_CONVERTER,
|
||||||
async_add_external_statistics,
|
async_add_external_statistics,
|
||||||
async_change_statistics_unit,
|
async_change_statistics_unit,
|
||||||
async_import_statistics,
|
async_import_statistics,
|
||||||
@ -327,25 +323,8 @@ async def ws_adjust_sum_statistics(
|
|||||||
def valid_units(statistics_unit: str | None, display_unit: str | None) -> bool:
|
def valid_units(statistics_unit: str | None, display_unit: str | None) -> bool:
|
||||||
if statistics_unit == display_unit:
|
if statistics_unit == display_unit:
|
||||||
return True
|
return True
|
||||||
if (
|
converter = STATISTIC_UNIT_TO_UNIT_CONVERTER.get(statistics_unit)
|
||||||
statistics_unit == DistanceConverter.NORMALIZED_UNIT
|
if converter is not None and display_unit in converter.VALID_UNITS:
|
||||||
and display_unit in DistanceConverter.VALID_UNITS
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
if statistics_unit == ENERGY_KILO_WATT_HOUR and display_unit in (
|
|
||||||
ENERGY_MEGA_WATT_HOUR,
|
|
||||||
ENERGY_WATT_HOUR,
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
if (
|
|
||||||
statistics_unit == MassConverter.NORMALIZED_UNIT
|
|
||||||
and display_unit in MassConverter.VALID_UNITS
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
if (
|
|
||||||
statistics_unit == VolumeConverter.NORMALIZED_UNIT
|
|
||||||
and display_unit in VolumeConverter.VALID_UNITS
|
|
||||||
):
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -234,19 +234,6 @@ UNIT_CONVERTERS: dict[str, type[BaseUnitConverter]] = {
|
|||||||
SensorDeviceClass.WEIGHT: MassConverter,
|
SensorDeviceClass.WEIGHT: MassConverter,
|
||||||
}
|
}
|
||||||
|
|
||||||
UNIT_RATIOS: dict[str, dict[str, float]] = {
|
|
||||||
SensorDeviceClass.DISTANCE: DistanceConverter.UNIT_CONVERSION,
|
|
||||||
SensorDeviceClass.PRESSURE: PressureConverter.UNIT_CONVERSION,
|
|
||||||
SensorDeviceClass.SPEED: SpeedConverter.UNIT_CONVERSION,
|
|
||||||
SensorDeviceClass.TEMPERATURE: {
|
|
||||||
TEMP_CELSIUS: 1.0,
|
|
||||||
TEMP_FAHRENHEIT: 1.8,
|
|
||||||
TEMP_KELVIN: 1.0,
|
|
||||||
},
|
|
||||||
SensorDeviceClass.VOLUME: VolumeConverter.UNIT_CONVERSION,
|
|
||||||
SensorDeviceClass.WEIGHT: MassConverter.UNIT_CONVERSION,
|
|
||||||
}
|
|
||||||
|
|
||||||
# mypy: disallow-any-generics
|
# mypy: disallow-any-generics
|
||||||
|
|
||||||
|
|
||||||
@ -456,6 +443,7 @@ class SensorEntity(Entity):
|
|||||||
):
|
):
|
||||||
assert unit_of_measurement
|
assert unit_of_measurement
|
||||||
assert native_unit_of_measurement
|
assert native_unit_of_measurement
|
||||||
|
converter = UNIT_CONVERTERS[device_class]
|
||||||
|
|
||||||
value_s = str(value)
|
value_s = str(value)
|
||||||
prec = len(value_s) - value_s.index(".") - 1 if "." in value_s else 0
|
prec = len(value_s) - value_s.index(".") - 1 if "." in value_s else 0
|
||||||
@ -465,8 +453,9 @@ class SensorEntity(Entity):
|
|||||||
ratio_log = max(
|
ratio_log = max(
|
||||||
0,
|
0,
|
||||||
log10(
|
log10(
|
||||||
UNIT_RATIOS[device_class][native_unit_of_measurement]
|
converter.get_unit_ratio(
|
||||||
/ UNIT_RATIOS[device_class][unit_of_measurement]
|
native_unit_of_measurement, unit_of_measurement
|
||||||
|
)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
prec = prec + floor(ratio_log)
|
prec = prec + floor(ratio_log)
|
||||||
@ -474,7 +463,7 @@ class SensorEntity(Entity):
|
|||||||
# Suppress ValueError (Could not convert sensor_value to float)
|
# Suppress ValueError (Could not convert sensor_value to float)
|
||||||
with suppress(ValueError):
|
with suppress(ValueError):
|
||||||
value_f = float(value) # type: ignore[arg-type]
|
value_f = float(value) # type: ignore[arg-type]
|
||||||
value_f_new = UNIT_CONVERTERS[device_class].convert(
|
value_f_new = converter.convert(
|
||||||
value_f,
|
value_f,
|
||||||
native_unit_of_measurement,
|
native_unit_of_measurement,
|
||||||
unit_of_measurement,
|
unit_of_measurement,
|
||||||
|
@ -17,7 +17,8 @@ from homeassistant.const import ( # pylint: disable=unused-import # noqa: F401
|
|||||||
|
|
||||||
from .unit_conversion import PressureConverter
|
from .unit_conversion import PressureConverter
|
||||||
|
|
||||||
UNIT_CONVERSION: dict[str, float] = PressureConverter.UNIT_CONVERSION
|
# pylint: disable-next=protected-access
|
||||||
|
UNIT_CONVERSION: dict[str, float] = PressureConverter._UNIT_CONVERSION
|
||||||
VALID_UNITS = PressureConverter.VALID_UNITS
|
VALID_UNITS = PressureConverter.VALID_UNITS
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ from .unit_conversion import ( # pylint: disable=unused-import # noqa: F401
|
|||||||
SpeedConverter,
|
SpeedConverter,
|
||||||
)
|
)
|
||||||
|
|
||||||
UNIT_CONVERSION = SpeedConverter.UNIT_CONVERSION
|
# pylint: disable-next=protected-access
|
||||||
|
UNIT_CONVERSION = SpeedConverter._UNIT_CONVERSION
|
||||||
VALID_UNITS = SpeedConverter.VALID_UNITS
|
VALID_UNITS = SpeedConverter.VALID_UNITS
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,11 +93,16 @@ class BaseUnitConverter:
|
|||||||
def convert(cls, value: float, from_unit: str, to_unit: str) -> float:
|
def convert(cls, value: float, from_unit: str, to_unit: str) -> float:
|
||||||
"""Convert one unit of measurement to another."""
|
"""Convert one unit of measurement to another."""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@abstractmethod
|
||||||
|
def get_unit_ratio(cls, from_unit: str, to_unit: str) -> float:
|
||||||
|
"""Get unit ratio between units of measurement."""
|
||||||
|
|
||||||
|
|
||||||
class BaseUnitConverterWithUnitConversion(BaseUnitConverter):
|
class BaseUnitConverterWithUnitConversion(BaseUnitConverter):
|
||||||
"""Define the format of a conversion utility."""
|
"""Define the format of a conversion utility."""
|
||||||
|
|
||||||
UNIT_CONVERSION: dict[str, float]
|
_UNIT_CONVERSION: dict[str, float]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def convert(cls, value: float, from_unit: str, to_unit: str) -> float:
|
def convert(cls, value: float, from_unit: str, to_unit: str) -> float:
|
||||||
@ -106,14 +111,14 @@ class BaseUnitConverterWithUnitConversion(BaseUnitConverter):
|
|||||||
return value
|
return value
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from_ratio = cls.UNIT_CONVERSION[from_unit]
|
from_ratio = cls._UNIT_CONVERSION[from_unit]
|
||||||
except KeyError as err:
|
except KeyError as err:
|
||||||
raise HomeAssistantError(
|
raise HomeAssistantError(
|
||||||
UNIT_NOT_RECOGNIZED_TEMPLATE.format(from_unit, cls.UNIT_CLASS)
|
UNIT_NOT_RECOGNIZED_TEMPLATE.format(from_unit, cls.UNIT_CLASS)
|
||||||
) from err
|
) from err
|
||||||
|
|
||||||
try:
|
try:
|
||||||
to_ratio = cls.UNIT_CONVERSION[to_unit]
|
to_ratio = cls._UNIT_CONVERSION[to_unit]
|
||||||
except KeyError as err:
|
except KeyError as err:
|
||||||
raise HomeAssistantError(
|
raise HomeAssistantError(
|
||||||
UNIT_NOT_RECOGNIZED_TEMPLATE.format(to_unit, cls.UNIT_CLASS)
|
UNIT_NOT_RECOGNIZED_TEMPLATE.format(to_unit, cls.UNIT_CLASS)
|
||||||
@ -122,13 +127,18 @@ class BaseUnitConverterWithUnitConversion(BaseUnitConverter):
|
|||||||
new_value = value / from_ratio
|
new_value = value / from_ratio
|
||||||
return new_value * to_ratio
|
return new_value * to_ratio
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_unit_ratio(cls, from_unit: str, to_unit: str) -> float:
|
||||||
|
"""Get unit ratio between units of measurement."""
|
||||||
|
return cls._UNIT_CONVERSION[from_unit] / cls._UNIT_CONVERSION[to_unit]
|
||||||
|
|
||||||
|
|
||||||
class DistanceConverter(BaseUnitConverterWithUnitConversion):
|
class DistanceConverter(BaseUnitConverterWithUnitConversion):
|
||||||
"""Utility to convert distance values."""
|
"""Utility to convert distance values."""
|
||||||
|
|
||||||
UNIT_CLASS = "distance"
|
UNIT_CLASS = "distance"
|
||||||
NORMALIZED_UNIT = LENGTH_METERS
|
NORMALIZED_UNIT = LENGTH_METERS
|
||||||
UNIT_CONVERSION: dict[str, float] = {
|
_UNIT_CONVERSION: dict[str, float] = {
|
||||||
LENGTH_METERS: 1,
|
LENGTH_METERS: 1,
|
||||||
LENGTH_MILLIMETERS: 1 / _MM_TO_M,
|
LENGTH_MILLIMETERS: 1 / _MM_TO_M,
|
||||||
LENGTH_CENTIMETERS: 1 / _CM_TO_M,
|
LENGTH_CENTIMETERS: 1 / _CM_TO_M,
|
||||||
@ -155,7 +165,7 @@ class EnergyConverter(BaseUnitConverterWithUnitConversion):
|
|||||||
|
|
||||||
UNIT_CLASS = "energy"
|
UNIT_CLASS = "energy"
|
||||||
NORMALIZED_UNIT = ENERGY_KILO_WATT_HOUR
|
NORMALIZED_UNIT = ENERGY_KILO_WATT_HOUR
|
||||||
UNIT_CONVERSION: dict[str, float] = {
|
_UNIT_CONVERSION: dict[str, float] = {
|
||||||
ENERGY_WATT_HOUR: 1 * 1000,
|
ENERGY_WATT_HOUR: 1 * 1000,
|
||||||
ENERGY_KILO_WATT_HOUR: 1,
|
ENERGY_KILO_WATT_HOUR: 1,
|
||||||
ENERGY_MEGA_WATT_HOUR: 1 / 1000,
|
ENERGY_MEGA_WATT_HOUR: 1 / 1000,
|
||||||
@ -172,7 +182,7 @@ class MassConverter(BaseUnitConverterWithUnitConversion):
|
|||||||
|
|
||||||
UNIT_CLASS = "mass"
|
UNIT_CLASS = "mass"
|
||||||
NORMALIZED_UNIT = MASS_GRAMS
|
NORMALIZED_UNIT = MASS_GRAMS
|
||||||
UNIT_CONVERSION: dict[str, float] = {
|
_UNIT_CONVERSION: dict[str, float] = {
|
||||||
MASS_MICROGRAMS: 1 * 1000 * 1000,
|
MASS_MICROGRAMS: 1 * 1000 * 1000,
|
||||||
MASS_MILLIGRAMS: 1 * 1000,
|
MASS_MILLIGRAMS: 1 * 1000,
|
||||||
MASS_GRAMS: 1,
|
MASS_GRAMS: 1,
|
||||||
@ -195,7 +205,7 @@ class PowerConverter(BaseUnitConverterWithUnitConversion):
|
|||||||
|
|
||||||
UNIT_CLASS = "power"
|
UNIT_CLASS = "power"
|
||||||
NORMALIZED_UNIT = POWER_WATT
|
NORMALIZED_UNIT = POWER_WATT
|
||||||
UNIT_CONVERSION: dict[str, float] = {
|
_UNIT_CONVERSION: dict[str, float] = {
|
||||||
POWER_WATT: 1,
|
POWER_WATT: 1,
|
||||||
POWER_KILO_WATT: 1 / 1000,
|
POWER_KILO_WATT: 1 / 1000,
|
||||||
}
|
}
|
||||||
@ -210,7 +220,7 @@ class PressureConverter(BaseUnitConverterWithUnitConversion):
|
|||||||
|
|
||||||
UNIT_CLASS = "pressure"
|
UNIT_CLASS = "pressure"
|
||||||
NORMALIZED_UNIT = PRESSURE_PA
|
NORMALIZED_UNIT = PRESSURE_PA
|
||||||
UNIT_CONVERSION: dict[str, float] = {
|
_UNIT_CONVERSION: dict[str, float] = {
|
||||||
PRESSURE_PA: 1,
|
PRESSURE_PA: 1,
|
||||||
PRESSURE_HPA: 1 / 100,
|
PRESSURE_HPA: 1 / 100,
|
||||||
PRESSURE_KPA: 1 / 1000,
|
PRESSURE_KPA: 1 / 1000,
|
||||||
@ -239,7 +249,7 @@ class SpeedConverter(BaseUnitConverterWithUnitConversion):
|
|||||||
|
|
||||||
UNIT_CLASS = "speed"
|
UNIT_CLASS = "speed"
|
||||||
NORMALIZED_UNIT = SPEED_METERS_PER_SECOND
|
NORMALIZED_UNIT = SPEED_METERS_PER_SECOND
|
||||||
UNIT_CONVERSION: dict[str, float] = {
|
_UNIT_CONVERSION: dict[str, float] = {
|
||||||
SPEED_FEET_PER_SECOND: 1 / _FOOT_TO_M,
|
SPEED_FEET_PER_SECOND: 1 / _FOOT_TO_M,
|
||||||
SPEED_INCHES_PER_DAY: _DAYS_TO_SECS / _IN_TO_M,
|
SPEED_INCHES_PER_DAY: _DAYS_TO_SECS / _IN_TO_M,
|
||||||
SPEED_INCHES_PER_HOUR: _HRS_TO_SECS / _IN_TO_M,
|
SPEED_INCHES_PER_HOUR: _HRS_TO_SECS / _IN_TO_M,
|
||||||
@ -271,6 +281,11 @@ class TemperatureConverter(BaseUnitConverter):
|
|||||||
TEMP_FAHRENHEIT,
|
TEMP_FAHRENHEIT,
|
||||||
TEMP_KELVIN,
|
TEMP_KELVIN,
|
||||||
}
|
}
|
||||||
|
_UNIT_RATIO = {
|
||||||
|
TEMP_CELSIUS: 1.0,
|
||||||
|
TEMP_FAHRENHEIT: 1.8,
|
||||||
|
TEMP_KELVIN: 1.0,
|
||||||
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def convert(
|
def convert(
|
||||||
@ -342,6 +357,11 @@ class TemperatureConverter(BaseUnitConverter):
|
|||||||
return celsius
|
return celsius
|
||||||
return celsius + 273.15
|
return celsius + 273.15
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_unit_ratio(cls, from_unit: str, to_unit: str) -> float:
|
||||||
|
"""Get unit ratio between units of measurement."""
|
||||||
|
return cls._UNIT_RATIO[from_unit] / cls._UNIT_RATIO[to_unit]
|
||||||
|
|
||||||
|
|
||||||
class VolumeConverter(BaseUnitConverterWithUnitConversion):
|
class VolumeConverter(BaseUnitConverterWithUnitConversion):
|
||||||
"""Utility to convert volume values."""
|
"""Utility to convert volume values."""
|
||||||
@ -349,7 +369,7 @@ class VolumeConverter(BaseUnitConverterWithUnitConversion):
|
|||||||
UNIT_CLASS = "volume"
|
UNIT_CLASS = "volume"
|
||||||
NORMALIZED_UNIT = VOLUME_CUBIC_METERS
|
NORMALIZED_UNIT = VOLUME_CUBIC_METERS
|
||||||
# Units in terms of m³
|
# Units in terms of m³
|
||||||
UNIT_CONVERSION: dict[str, float] = {
|
_UNIT_CONVERSION: dict[str, float] = {
|
||||||
VOLUME_LITERS: 1 / _L_TO_CUBIC_METER,
|
VOLUME_LITERS: 1 / _L_TO_CUBIC_METER,
|
||||||
VOLUME_MILLILITERS: 1 / _ML_TO_CUBIC_METER,
|
VOLUME_MILLILITERS: 1 / _ML_TO_CUBIC_METER,
|
||||||
VOLUME_GALLONS: 1 / _GALLON_TO_CUBIC_METER,
|
VOLUME_GALLONS: 1 / _GALLON_TO_CUBIC_METER,
|
||||||
|
@ -14,7 +14,8 @@ from homeassistant.const import ( # pylint: disable=unused-import # noqa: F401
|
|||||||
|
|
||||||
from .unit_conversion import VolumeConverter
|
from .unit_conversion import VolumeConverter
|
||||||
|
|
||||||
UNIT_CONVERSION = VolumeConverter.UNIT_CONVERSION
|
# pylint: disable-next=protected-access
|
||||||
|
UNIT_CONVERSION = VolumeConverter._UNIT_CONVERSION
|
||||||
VALID_UNITS = VolumeConverter.VALID_UNITS
|
VALID_UNITS = VolumeConverter.VALID_UNITS
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,6 +162,30 @@ def test_convert_nonnumeric_value(
|
|||||||
converter.convert("a", from_unit, to_unit)
|
converter.convert("a", from_unit, to_unit)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"converter,from_unit,to_unit,expected",
|
||||||
|
[
|
||||||
|
(DistanceConverter, LENGTH_KILOMETERS, LENGTH_METERS, 1 / 1000),
|
||||||
|
(EnergyConverter, ENERGY_WATT_HOUR, ENERGY_KILO_WATT_HOUR, 1000),
|
||||||
|
(PowerConverter, POWER_WATT, POWER_KILO_WATT, 1000),
|
||||||
|
(PressureConverter, PRESSURE_HPA, PRESSURE_INHG, pytest.approx(33.86389)),
|
||||||
|
(
|
||||||
|
SpeedConverter,
|
||||||
|
SPEED_KILOMETERS_PER_HOUR,
|
||||||
|
SPEED_MILES_PER_HOUR,
|
||||||
|
pytest.approx(1.609343),
|
||||||
|
),
|
||||||
|
(TemperatureConverter, TEMP_CELSIUS, TEMP_FAHRENHEIT, 1 / 1.8),
|
||||||
|
(VolumeConverter, VOLUME_GALLONS, VOLUME_LITERS, pytest.approx(0.264172)),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_get_unit_ratio(
|
||||||
|
converter: type[BaseUnitConverter], from_unit: str, to_unit: str, expected: float
|
||||||
|
) -> None:
|
||||||
|
"""Test unit ratio."""
|
||||||
|
assert converter.get_unit_ratio(from_unit, to_unit) == expected
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"value,from_unit,expected,to_unit",
|
"value,from_unit,expected,to_unit",
|
||||||
[
|
[
|
||||||
|
Loading…
x
Reference in New Issue
Block a user