2018-10-11 08:55:22 +00:00
|
|
|
"""Volume conversion util functions."""
|
2021-07-18 12:43:47 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2018-10-11 08:55:22 +00:00
|
|
|
from numbers import Number
|
2019-12-09 15:42:10 +00:00
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
from homeassistant.const import (
|
2019-12-09 15:42:10 +00:00
|
|
|
UNIT_NOT_RECOGNIZED_TEMPLATE,
|
|
|
|
VOLUME,
|
2021-08-11 16:58:19 +00:00
|
|
|
VOLUME_CUBIC_FEET,
|
|
|
|
VOLUME_CUBIC_METERS,
|
2019-12-09 15:42:10 +00:00
|
|
|
VOLUME_FLUID_OUNCE,
|
|
|
|
VOLUME_GALLONS,
|
2019-07-31 19:25:30 +00:00
|
|
|
VOLUME_LITERS,
|
|
|
|
VOLUME_MILLILITERS,
|
|
|
|
)
|
2018-10-11 08:55:22 +00:00
|
|
|
|
2022-09-07 14:18:00 +00:00
|
|
|
from .distance import FOOT_TO_M, IN_TO_M
|
|
|
|
|
2021-07-20 12:13:51 +00:00
|
|
|
VALID_UNITS: tuple[str, ...] = (
|
2021-07-18 12:43:47 +00:00
|
|
|
VOLUME_LITERS,
|
|
|
|
VOLUME_MILLILITERS,
|
|
|
|
VOLUME_GALLONS,
|
|
|
|
VOLUME_FLUID_OUNCE,
|
2021-08-11 16:58:19 +00:00
|
|
|
VOLUME_CUBIC_METERS,
|
|
|
|
VOLUME_CUBIC_FEET,
|
2021-07-18 12:43:47 +00:00
|
|
|
)
|
2018-10-11 08:55:22 +00:00
|
|
|
|
2022-09-07 14:18:00 +00:00
|
|
|
ML_TO_L = 0.001 # 1 mL = 0.001 L
|
|
|
|
CUBIC_METER_TO_L = 1000 # 1 m3 = 1000 L
|
|
|
|
GALLON_TO_L = 231 * pow(IN_TO_M, 3) * CUBIC_METER_TO_L # US gallon is 231 cubic inches
|
|
|
|
FLUID_OUNCE_TO_L = GALLON_TO_L / 128 # 128 fluid ounces in a US gallon
|
|
|
|
CUBIC_FOOT_TO_L = CUBIC_METER_TO_L * pow(FOOT_TO_M, 3)
|
|
|
|
|
|
|
|
# Units in terms of L
|
|
|
|
UNIT_CONVERSION: dict[str, float] = {
|
|
|
|
VOLUME_LITERS: 1,
|
|
|
|
VOLUME_MILLILITERS: 1 / ML_TO_L,
|
|
|
|
VOLUME_GALLONS: 1 / GALLON_TO_L,
|
|
|
|
VOLUME_FLUID_OUNCE: 1 / FLUID_OUNCE_TO_L,
|
|
|
|
VOLUME_CUBIC_METERS: 1 / CUBIC_METER_TO_L,
|
|
|
|
VOLUME_CUBIC_FEET: 1 / CUBIC_FOOT_TO_L,
|
|
|
|
}
|
|
|
|
|
2018-10-11 08:55:22 +00:00
|
|
|
|
2021-08-11 16:58:19 +00:00
|
|
|
def liter_to_gallon(liter: float) -> float:
|
2018-10-11 08:55:22 +00:00
|
|
|
"""Convert a volume measurement in Liter to Gallon."""
|
2022-09-07 14:18:00 +00:00
|
|
|
return _convert(liter, VOLUME_LITERS, VOLUME_GALLONS)
|
2018-10-11 08:55:22 +00:00
|
|
|
|
|
|
|
|
2021-08-11 16:58:19 +00:00
|
|
|
def gallon_to_liter(gallon: float) -> float:
|
2018-10-11 08:55:22 +00:00
|
|
|
"""Convert a volume measurement in Gallon to Liter."""
|
2022-09-07 14:18:00 +00:00
|
|
|
return _convert(gallon, VOLUME_GALLONS, VOLUME_LITERS)
|
2018-10-11 08:55:22 +00:00
|
|
|
|
|
|
|
|
2021-08-11 16:58:19 +00:00
|
|
|
def cubic_meter_to_cubic_feet(cubic_meter: float) -> float:
|
|
|
|
"""Convert a volume measurement in cubic meter to cubic feet."""
|
2022-09-07 14:18:00 +00:00
|
|
|
return _convert(cubic_meter, VOLUME_CUBIC_METERS, VOLUME_CUBIC_FEET)
|
2021-08-11 16:58:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
def cubic_feet_to_cubic_meter(cubic_feet: float) -> float:
|
|
|
|
"""Convert a volume measurement in cubic feet to cubic meter."""
|
2022-09-07 14:18:00 +00:00
|
|
|
return _convert(cubic_feet, VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS)
|
2021-08-11 16:58:19 +00:00
|
|
|
|
|
|
|
|
2021-07-20 12:13:51 +00:00
|
|
|
def convert(volume: float, from_unit: str, to_unit: str) -> float:
|
2018-10-11 08:55:22 +00:00
|
|
|
"""Convert a temperature from one unit to another."""
|
|
|
|
if from_unit not in VALID_UNITS:
|
2019-07-31 19:25:30 +00:00
|
|
|
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(from_unit, VOLUME))
|
2018-10-11 08:55:22 +00:00
|
|
|
if to_unit not in VALID_UNITS:
|
|
|
|
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(to_unit, VOLUME))
|
|
|
|
|
|
|
|
if not isinstance(volume, Number):
|
2019-08-23 16:53:33 +00:00
|
|
|
raise TypeError(f"{volume} is not of numeric type")
|
2018-10-11 08:55:22 +00:00
|
|
|
|
2020-03-12 10:52:20 +00:00
|
|
|
if from_unit == to_unit:
|
2018-10-11 08:55:22 +00:00
|
|
|
return volume
|
2022-09-07 14:18:00 +00:00
|
|
|
return _convert(volume, from_unit, to_unit)
|
|
|
|
|
2018-10-11 08:55:22 +00:00
|
|
|
|
2022-09-07 14:18:00 +00:00
|
|
|
def _convert(volume: float, from_unit: str, to_unit: str) -> float:
|
|
|
|
"""Convert a temperature from one unit to another, bypassing checks."""
|
|
|
|
liters = volume / UNIT_CONVERSION[from_unit]
|
|
|
|
return liters * UNIT_CONVERSION[to_unit]
|