mirror of
https://github.com/home-assistant/core.git
synced 2025-07-29 18:28:14 +02:00
Area units and conversion between metric and US (#123563)
* area conversions * start work on tests * add number device class * update unit conversions to utilise distance constants * add area unit * update test unit system * update device condition and trigger * update statistic unit converters * further tests work WIP * update test unit system * add missing string translations * fix websocket tests * add deprecated notice * add more missing strings and missing initialisation of unit system * adjust icon and remove strings from scrape and random * Fix acre to meters conversion Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * Tidy up valid units Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * fix ordering of area * update order alphabetically * fix broken test * update test_init * Update homeassistant/const.py Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> * remove deprecated unit and fix alphabetical order * change deprecation and add tests, change to millimeter conversion for inches * fix order * re-order defs alphabetically * add measurement as well * update icons * fix up Deprecation of area square meters * Update core integrations to UnitOfArea * update test recorder tests * unit system tests in alphabetical * update snapshot * rebuild * revert alphabetization of functions * other revert of alphabetical order --------- Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
This commit is contained in:
@ -9,6 +9,7 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
ACCUMULATED_PRECIPITATION,
|
||||
AREA,
|
||||
LENGTH,
|
||||
MASS,
|
||||
PRESSURE,
|
||||
@ -16,6 +17,7 @@ from homeassistant.const import (
|
||||
UNIT_NOT_RECOGNIZED_TEMPLATE,
|
||||
VOLUME,
|
||||
WIND_SPEED,
|
||||
UnitOfArea,
|
||||
UnitOfLength,
|
||||
UnitOfMass,
|
||||
UnitOfPrecipitationDepth,
|
||||
@ -27,6 +29,7 @@ from homeassistant.const import (
|
||||
)
|
||||
|
||||
from .unit_conversion import (
|
||||
AreaConverter,
|
||||
DistanceConverter,
|
||||
PressureConverter,
|
||||
SpeedConverter,
|
||||
@ -41,6 +44,8 @@ _CONF_UNIT_SYSTEM_IMPERIAL: Final = "imperial"
|
||||
_CONF_UNIT_SYSTEM_METRIC: Final = "metric"
|
||||
_CONF_UNIT_SYSTEM_US_CUSTOMARY: Final = "us_customary"
|
||||
|
||||
AREA_UNITS = AreaConverter.VALID_UNITS
|
||||
|
||||
LENGTH_UNITS = DistanceConverter.VALID_UNITS
|
||||
|
||||
MASS_UNITS: set[str] = {
|
||||
@ -66,6 +71,7 @@ _VALID_BY_TYPE: dict[str, set[str] | set[str | None]] = {
|
||||
MASS: MASS_UNITS,
|
||||
VOLUME: VOLUME_UNITS,
|
||||
PRESSURE: PRESSURE_UNITS,
|
||||
AREA: AREA_UNITS,
|
||||
}
|
||||
|
||||
|
||||
@ -84,6 +90,7 @@ class UnitSystem:
|
||||
name: str,
|
||||
*,
|
||||
accumulated_precipitation: UnitOfPrecipitationDepth,
|
||||
area: UnitOfArea,
|
||||
conversions: dict[tuple[SensorDeviceClass | str | None, str | None], str],
|
||||
length: UnitOfLength,
|
||||
mass: UnitOfMass,
|
||||
@ -97,6 +104,7 @@ class UnitSystem:
|
||||
UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit, unit_type)
|
||||
for unit, unit_type in (
|
||||
(accumulated_precipitation, ACCUMULATED_PRECIPITATION),
|
||||
(area, AREA),
|
||||
(temperature, TEMPERATURE),
|
||||
(length, LENGTH),
|
||||
(wind_speed, WIND_SPEED),
|
||||
@ -112,10 +120,11 @@ class UnitSystem:
|
||||
|
||||
self._name = name
|
||||
self.accumulated_precipitation_unit = accumulated_precipitation
|
||||
self.temperature_unit = temperature
|
||||
self.area_unit = area
|
||||
self.length_unit = length
|
||||
self.mass_unit = mass
|
||||
self.pressure_unit = pressure
|
||||
self.temperature_unit = temperature
|
||||
self.volume_unit = volume
|
||||
self.wind_speed_unit = wind_speed
|
||||
self._conversions = conversions
|
||||
@ -149,6 +158,16 @@ class UnitSystem:
|
||||
precip, from_unit, self.accumulated_precipitation_unit
|
||||
)
|
||||
|
||||
def area(self, area: float | None, from_unit: str) -> float:
|
||||
"""Convert the given area to this unit system."""
|
||||
if not isinstance(area, Number):
|
||||
raise TypeError(f"{area!s} is not a numeric value.")
|
||||
|
||||
# type ignore: https://github.com/python/mypy/issues/7207
|
||||
return AreaConverter.convert( # type: ignore[unreachable]
|
||||
area, from_unit, self.area_unit
|
||||
)
|
||||
|
||||
def pressure(self, pressure: float | None, from_unit: str) -> float:
|
||||
"""Convert the given pressure to this unit system."""
|
||||
if not isinstance(pressure, Number):
|
||||
@ -184,6 +203,7 @@ class UnitSystem:
|
||||
return {
|
||||
LENGTH: self.length_unit,
|
||||
ACCUMULATED_PRECIPITATION: self.accumulated_precipitation_unit,
|
||||
AREA: self.area_unit,
|
||||
MASS: self.mass_unit,
|
||||
PRESSURE: self.pressure_unit,
|
||||
TEMPERATURE: self.temperature_unit,
|
||||
@ -234,6 +254,12 @@ METRIC_SYSTEM = UnitSystem(
|
||||
for unit in UnitOfPressure
|
||||
if unit != UnitOfPressure.HPA
|
||||
},
|
||||
# Convert non-metric area
|
||||
("area", UnitOfArea.SQUARE_INCHES): UnitOfArea.SQUARE_CENTIMETERS,
|
||||
("area", UnitOfArea.SQUARE_FEET): UnitOfArea.SQUARE_METERS,
|
||||
("area", UnitOfArea.SQUARE_MILES): UnitOfArea.SQUARE_KILOMETERS,
|
||||
("area", UnitOfArea.SQUARE_YARDS): UnitOfArea.SQUARE_METERS,
|
||||
("area", UnitOfArea.ACRES): UnitOfArea.HECTARES,
|
||||
# Convert non-metric distances
|
||||
("distance", UnitOfLength.FEET): UnitOfLength.METERS,
|
||||
("distance", UnitOfLength.INCHES): UnitOfLength.MILLIMETERS,
|
||||
@ -285,6 +311,7 @@ METRIC_SYSTEM = UnitSystem(
|
||||
if unit not in (UnitOfSpeed.KILOMETERS_PER_HOUR, UnitOfSpeed.KNOTS)
|
||||
},
|
||||
},
|
||||
area=UnitOfArea.SQUARE_METERS,
|
||||
length=UnitOfLength.KILOMETERS,
|
||||
mass=UnitOfMass.GRAMS,
|
||||
pressure=UnitOfPressure.PA,
|
||||
@ -303,6 +330,12 @@ US_CUSTOMARY_SYSTEM = UnitSystem(
|
||||
for unit in UnitOfPressure
|
||||
if unit != UnitOfPressure.INHG
|
||||
},
|
||||
# Convert non-USCS areas
|
||||
("area", UnitOfArea.SQUARE_METERS): UnitOfArea.SQUARE_FEET,
|
||||
("area", UnitOfArea.SQUARE_CENTIMETERS): UnitOfArea.SQUARE_INCHES,
|
||||
("area", UnitOfArea.SQUARE_MILLIMETERS): UnitOfArea.SQUARE_INCHES,
|
||||
("area", UnitOfArea.SQUARE_KILOMETERS): UnitOfArea.SQUARE_MILES,
|
||||
("area", UnitOfArea.HECTARES): UnitOfArea.ACRES,
|
||||
# Convert non-USCS distances
|
||||
("distance", UnitOfLength.CENTIMETERS): UnitOfLength.INCHES,
|
||||
("distance", UnitOfLength.KILOMETERS): UnitOfLength.MILES,
|
||||
@ -356,6 +389,7 @@ US_CUSTOMARY_SYSTEM = UnitSystem(
|
||||
if unit not in (UnitOfSpeed.KNOTS, UnitOfSpeed.MILES_PER_HOUR)
|
||||
},
|
||||
},
|
||||
area=UnitOfArea.SQUARE_FEET,
|
||||
length=UnitOfLength.MILES,
|
||||
mass=UnitOfMass.POUNDS,
|
||||
pressure=UnitOfPressure.PSI,
|
||||
|
Reference in New Issue
Block a user