Add speed to units system (#58437)
* Use speed units in unit system * Use more obvious conversion factor for unit system speed test * Use wind_speed instead of speed, use m/s
This commit is contained in:
parent
3dc0b9537c
commit
7cc7bbb76d
4 changed files with 76 additions and 1 deletions
|
@ -686,6 +686,7 @@ PRESSURE: Final = "pressure"
|
||||||
VOLUME: Final = "volume"
|
VOLUME: Final = "volume"
|
||||||
TEMPERATURE: Final = "temperature"
|
TEMPERATURE: Final = "temperature"
|
||||||
SPEED: Final = "speed"
|
SPEED: Final = "speed"
|
||||||
|
WIND_SPEED: Final = "wind_speed"
|
||||||
ILLUMINANCE: Final = "illuminance"
|
ILLUMINANCE: Final = "illuminance"
|
||||||
|
|
||||||
WEEKDAYS: Final[list[str]] = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
|
WEEKDAYS: Final[list[str]] = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]
|
||||||
|
|
|
@ -17,6 +17,8 @@ from homeassistant.const import (
|
||||||
PRESSURE,
|
PRESSURE,
|
||||||
PRESSURE_PA,
|
PRESSURE_PA,
|
||||||
PRESSURE_PSI,
|
PRESSURE_PSI,
|
||||||
|
SPEED_METERS_PER_SECOND,
|
||||||
|
SPEED_MILES_PER_HOUR,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
TEMP_FAHRENHEIT,
|
TEMP_FAHRENHEIT,
|
||||||
TEMPERATURE,
|
TEMPERATURE,
|
||||||
|
@ -24,10 +26,12 @@ from homeassistant.const import (
|
||||||
VOLUME,
|
VOLUME,
|
||||||
VOLUME_GALLONS,
|
VOLUME_GALLONS,
|
||||||
VOLUME_LITERS,
|
VOLUME_LITERS,
|
||||||
|
WIND_SPEED,
|
||||||
)
|
)
|
||||||
from homeassistant.util import (
|
from homeassistant.util import (
|
||||||
distance as distance_util,
|
distance as distance_util,
|
||||||
pressure as pressure_util,
|
pressure as pressure_util,
|
||||||
|
speed as speed_util,
|
||||||
temperature as temperature_util,
|
temperature as temperature_util,
|
||||||
volume as volume_util,
|
volume as volume_util,
|
||||||
)
|
)
|
||||||
|
@ -42,6 +46,8 @@ PRESSURE_UNITS = pressure_util.VALID_UNITS
|
||||||
|
|
||||||
VOLUME_UNITS = volume_util.VALID_UNITS
|
VOLUME_UNITS = volume_util.VALID_UNITS
|
||||||
|
|
||||||
|
WIND_SPEED_UNITS = speed_util.VALID_UNITS
|
||||||
|
|
||||||
TEMPERATURE_UNITS: tuple[str, ...] = (TEMP_FAHRENHEIT, TEMP_CELSIUS)
|
TEMPERATURE_UNITS: tuple[str, ...] = (TEMP_FAHRENHEIT, TEMP_CELSIUS)
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,6 +55,8 @@ def is_valid_unit(unit: str, unit_type: str) -> bool:
|
||||||
"""Check if the unit is valid for it's type."""
|
"""Check if the unit is valid for it's type."""
|
||||||
if unit_type == LENGTH:
|
if unit_type == LENGTH:
|
||||||
units = LENGTH_UNITS
|
units = LENGTH_UNITS
|
||||||
|
elif unit_type == WIND_SPEED:
|
||||||
|
units = WIND_SPEED_UNITS
|
||||||
elif unit_type == TEMPERATURE:
|
elif unit_type == TEMPERATURE:
|
||||||
units = TEMPERATURE_UNITS
|
units = TEMPERATURE_UNITS
|
||||||
elif unit_type == MASS:
|
elif unit_type == MASS:
|
||||||
|
@ -71,6 +79,7 @@ class UnitSystem:
|
||||||
name: str,
|
name: str,
|
||||||
temperature: str,
|
temperature: str,
|
||||||
length: str,
|
length: str,
|
||||||
|
wind_speed: str,
|
||||||
volume: str,
|
volume: str,
|
||||||
mass: str,
|
mass: str,
|
||||||
pressure: str,
|
pressure: str,
|
||||||
|
@ -81,6 +90,7 @@ class UnitSystem:
|
||||||
for unit, unit_type in (
|
for unit, unit_type in (
|
||||||
(temperature, TEMPERATURE),
|
(temperature, TEMPERATURE),
|
||||||
(length, LENGTH),
|
(length, LENGTH),
|
||||||
|
(wind_speed, WIND_SPEED),
|
||||||
(volume, VOLUME),
|
(volume, VOLUME),
|
||||||
(mass, MASS),
|
(mass, MASS),
|
||||||
(pressure, PRESSURE),
|
(pressure, PRESSURE),
|
||||||
|
@ -97,6 +107,7 @@ class UnitSystem:
|
||||||
self.mass_unit = mass
|
self.mass_unit = mass
|
||||||
self.pressure_unit = pressure
|
self.pressure_unit = pressure
|
||||||
self.volume_unit = volume
|
self.volume_unit = volume
|
||||||
|
self.wind_speed_unit = wind_speed
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_metric(self) -> bool:
|
def is_metric(self) -> bool:
|
||||||
|
@ -130,6 +141,14 @@ class UnitSystem:
|
||||||
pressure, from_unit, self.pressure_unit
|
pressure, from_unit, self.pressure_unit
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def wind_speed(self, wind_speed: float | None, from_unit: str) -> float:
|
||||||
|
"""Convert the given wind_speed to this unit system."""
|
||||||
|
if not isinstance(wind_speed, Number):
|
||||||
|
raise TypeError(f"{wind_speed!s} is not a numeric value.")
|
||||||
|
|
||||||
|
# type ignore: https://github.com/python/mypy/issues/7207
|
||||||
|
return speed_util.convert(wind_speed, from_unit, self.wind_speed_unit) # type: ignore
|
||||||
|
|
||||||
def volume(self, volume: float | None, from_unit: str) -> float:
|
def volume(self, volume: float | None, from_unit: str) -> float:
|
||||||
"""Convert the given volume to this unit system."""
|
"""Convert the given volume to this unit system."""
|
||||||
if not isinstance(volume, Number):
|
if not isinstance(volume, Number):
|
||||||
|
@ -146,6 +165,7 @@ class UnitSystem:
|
||||||
PRESSURE: self.pressure_unit,
|
PRESSURE: self.pressure_unit,
|
||||||
TEMPERATURE: self.temperature_unit,
|
TEMPERATURE: self.temperature_unit,
|
||||||
VOLUME: self.volume_unit,
|
VOLUME: self.volume_unit,
|
||||||
|
WIND_SPEED: self.wind_speed_unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,6 +173,7 @@ METRIC_SYSTEM = UnitSystem(
|
||||||
CONF_UNIT_SYSTEM_METRIC,
|
CONF_UNIT_SYSTEM_METRIC,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
LENGTH_KILOMETERS,
|
LENGTH_KILOMETERS,
|
||||||
|
SPEED_METERS_PER_SECOND,
|
||||||
VOLUME_LITERS,
|
VOLUME_LITERS,
|
||||||
MASS_GRAMS,
|
MASS_GRAMS,
|
||||||
PRESSURE_PA,
|
PRESSURE_PA,
|
||||||
|
@ -162,6 +183,7 @@ IMPERIAL_SYSTEM = UnitSystem(
|
||||||
CONF_UNIT_SYSTEM_IMPERIAL,
|
CONF_UNIT_SYSTEM_IMPERIAL,
|
||||||
TEMP_FAHRENHEIT,
|
TEMP_FAHRENHEIT,
|
||||||
LENGTH_MILES,
|
LENGTH_MILES,
|
||||||
|
SPEED_MILES_PER_HOUR,
|
||||||
VOLUME_GALLONS,
|
VOLUME_GALLONS,
|
||||||
MASS_POUNDS,
|
MASS_POUNDS,
|
||||||
PRESSURE_PSI,
|
PRESSURE_PSI,
|
||||||
|
|
|
@ -14,6 +14,7 @@ from homeassistant.const import (
|
||||||
LENGTH_METERS,
|
LENGTH_METERS,
|
||||||
MASS_GRAMS,
|
MASS_GRAMS,
|
||||||
PRESSURE_PA,
|
PRESSURE_PA,
|
||||||
|
SPEED_KILOMETERS_PER_HOUR,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
VOLUME_LITERS,
|
VOLUME_LITERS,
|
||||||
)
|
)
|
||||||
|
@ -34,7 +35,13 @@ from tests.common import (
|
||||||
def _set_up_units(hass):
|
def _set_up_units(hass):
|
||||||
"""Set up the tests."""
|
"""Set up the tests."""
|
||||||
hass.config.units = UnitSystem(
|
hass.config.units = UnitSystem(
|
||||||
"custom", TEMP_CELSIUS, LENGTH_METERS, VOLUME_LITERS, MASS_GRAMS, PRESSURE_PA
|
"custom",
|
||||||
|
TEMP_CELSIUS,
|
||||||
|
LENGTH_METERS,
|
||||||
|
SPEED_KILOMETERS_PER_HOUR,
|
||||||
|
VOLUME_LITERS,
|
||||||
|
MASS_GRAMS,
|
||||||
|
PRESSURE_PA,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,12 @@ from homeassistant.const import (
|
||||||
MASS_GRAMS,
|
MASS_GRAMS,
|
||||||
PRESSURE,
|
PRESSURE,
|
||||||
PRESSURE_PA,
|
PRESSURE_PA,
|
||||||
|
SPEED_METERS_PER_SECOND,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
TEMPERATURE,
|
TEMPERATURE,
|
||||||
VOLUME,
|
VOLUME,
|
||||||
VOLUME_LITERS,
|
VOLUME_LITERS,
|
||||||
|
WIND_SPEED,
|
||||||
)
|
)
|
||||||
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM, UnitSystem
|
from homeassistant.util.unit_system import IMPERIAL_SYSTEM, METRIC_SYSTEM, UnitSystem
|
||||||
|
|
||||||
|
@ -27,6 +29,7 @@ def test_invalid_units():
|
||||||
SYSTEM_NAME,
|
SYSTEM_NAME,
|
||||||
INVALID_UNIT,
|
INVALID_UNIT,
|
||||||
LENGTH_METERS,
|
LENGTH_METERS,
|
||||||
|
SPEED_METERS_PER_SECOND,
|
||||||
VOLUME_LITERS,
|
VOLUME_LITERS,
|
||||||
MASS_GRAMS,
|
MASS_GRAMS,
|
||||||
PRESSURE_PA,
|
PRESSURE_PA,
|
||||||
|
@ -37,6 +40,7 @@ def test_invalid_units():
|
||||||
SYSTEM_NAME,
|
SYSTEM_NAME,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
INVALID_UNIT,
|
INVALID_UNIT,
|
||||||
|
SPEED_METERS_PER_SECOND,
|
||||||
VOLUME_LITERS,
|
VOLUME_LITERS,
|
||||||
MASS_GRAMS,
|
MASS_GRAMS,
|
||||||
PRESSURE_PA,
|
PRESSURE_PA,
|
||||||
|
@ -48,6 +52,7 @@ def test_invalid_units():
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
LENGTH_METERS,
|
LENGTH_METERS,
|
||||||
INVALID_UNIT,
|
INVALID_UNIT,
|
||||||
|
VOLUME_LITERS,
|
||||||
MASS_GRAMS,
|
MASS_GRAMS,
|
||||||
PRESSURE_PA,
|
PRESSURE_PA,
|
||||||
)
|
)
|
||||||
|
@ -57,6 +62,18 @@ def test_invalid_units():
|
||||||
SYSTEM_NAME,
|
SYSTEM_NAME,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
LENGTH_METERS,
|
LENGTH_METERS,
|
||||||
|
SPEED_METERS_PER_SECOND,
|
||||||
|
INVALID_UNIT,
|
||||||
|
MASS_GRAMS,
|
||||||
|
PRESSURE_PA,
|
||||||
|
)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
UnitSystem(
|
||||||
|
SYSTEM_NAME,
|
||||||
|
TEMP_CELSIUS,
|
||||||
|
LENGTH_METERS,
|
||||||
|
SPEED_METERS_PER_SECOND,
|
||||||
VOLUME_LITERS,
|
VOLUME_LITERS,
|
||||||
INVALID_UNIT,
|
INVALID_UNIT,
|
||||||
PRESSURE_PA,
|
PRESSURE_PA,
|
||||||
|
@ -67,6 +84,7 @@ def test_invalid_units():
|
||||||
SYSTEM_NAME,
|
SYSTEM_NAME,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
LENGTH_METERS,
|
LENGTH_METERS,
|
||||||
|
SPEED_METERS_PER_SECOND,
|
||||||
VOLUME_LITERS,
|
VOLUME_LITERS,
|
||||||
MASS_GRAMS,
|
MASS_GRAMS,
|
||||||
INVALID_UNIT,
|
INVALID_UNIT,
|
||||||
|
@ -79,6 +97,8 @@ def test_invalid_value():
|
||||||
METRIC_SYSTEM.length("25a", LENGTH_KILOMETERS)
|
METRIC_SYSTEM.length("25a", LENGTH_KILOMETERS)
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
METRIC_SYSTEM.temperature("50K", TEMP_CELSIUS)
|
METRIC_SYSTEM.temperature("50K", TEMP_CELSIUS)
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
METRIC_SYSTEM.wind_speed("50km/h", SPEED_METERS_PER_SECOND)
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
METRIC_SYSTEM.volume("50L", VOLUME_LITERS)
|
METRIC_SYSTEM.volume("50L", VOLUME_LITERS)
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
|
@ -89,6 +109,7 @@ def test_as_dict():
|
||||||
"""Test that the as_dict() method returns the expected dictionary."""
|
"""Test that the as_dict() method returns the expected dictionary."""
|
||||||
expected = {
|
expected = {
|
||||||
LENGTH: LENGTH_KILOMETERS,
|
LENGTH: LENGTH_KILOMETERS,
|
||||||
|
WIND_SPEED: SPEED_METERS_PER_SECOND,
|
||||||
TEMPERATURE: TEMP_CELSIUS,
|
TEMPERATURE: TEMP_CELSIUS,
|
||||||
VOLUME: VOLUME_LITERS,
|
VOLUME: VOLUME_LITERS,
|
||||||
MASS: MASS_GRAMS,
|
MASS: MASS_GRAMS,
|
||||||
|
@ -142,6 +163,29 @@ def test_length_to_imperial():
|
||||||
assert IMPERIAL_SYSTEM.length(5, METRIC_SYSTEM.length_unit) == 3.106855
|
assert IMPERIAL_SYSTEM.length(5, METRIC_SYSTEM.length_unit) == 3.106855
|
||||||
|
|
||||||
|
|
||||||
|
def test_wind_speed_unknown_unit():
|
||||||
|
"""Test wind_speed conversion with unknown from unit."""
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
METRIC_SYSTEM.length(5, "turtles")
|
||||||
|
|
||||||
|
|
||||||
|
def test_wind_speed_to_metric():
|
||||||
|
"""Test length conversion to metric system."""
|
||||||
|
assert METRIC_SYSTEM.wind_speed(100, METRIC_SYSTEM.wind_speed_unit) == 100
|
||||||
|
# 1 m/s is about 2.237 mph
|
||||||
|
assert METRIC_SYSTEM.wind_speed(
|
||||||
|
2237, IMPERIAL_SYSTEM.wind_speed_unit
|
||||||
|
) == pytest.approx(1000, abs=0.1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_wind_speed_to_imperial():
|
||||||
|
"""Test wind_speed conversion to imperial system."""
|
||||||
|
assert IMPERIAL_SYSTEM.wind_speed(100, IMPERIAL_SYSTEM.wind_speed_unit) == 100
|
||||||
|
assert IMPERIAL_SYSTEM.wind_speed(
|
||||||
|
1000, METRIC_SYSTEM.wind_speed_unit
|
||||||
|
) == pytest.approx(2237, abs=0.1)
|
||||||
|
|
||||||
|
|
||||||
def test_pressure_same_unit():
|
def test_pressure_same_unit():
|
||||||
"""Test no conversion happens if to unit is same as from unit."""
|
"""Test no conversion happens if to unit is same as from unit."""
|
||||||
assert METRIC_SYSTEM.pressure(5, METRIC_SYSTEM.pressure_unit) == 5
|
assert METRIC_SYSTEM.pressure(5, METRIC_SYSTEM.pressure_unit) == 5
|
||||||
|
@ -172,6 +216,7 @@ def test_pressure_to_imperial():
|
||||||
def test_properties():
|
def test_properties():
|
||||||
"""Test the unit properties are returned as expected."""
|
"""Test the unit properties are returned as expected."""
|
||||||
assert METRIC_SYSTEM.length_unit == LENGTH_KILOMETERS
|
assert METRIC_SYSTEM.length_unit == LENGTH_KILOMETERS
|
||||||
|
assert METRIC_SYSTEM.wind_speed_unit == SPEED_METERS_PER_SECOND
|
||||||
assert METRIC_SYSTEM.temperature_unit == TEMP_CELSIUS
|
assert METRIC_SYSTEM.temperature_unit == TEMP_CELSIUS
|
||||||
assert METRIC_SYSTEM.mass_unit == MASS_GRAMS
|
assert METRIC_SYSTEM.mass_unit == MASS_GRAMS
|
||||||
assert METRIC_SYSTEM.volume_unit == VOLUME_LITERS
|
assert METRIC_SYSTEM.volume_unit == VOLUME_LITERS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue