Skip to content

Commit

Permalink
Area units and conversion between metric and US (#123563)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* Tidy up valid units

Co-authored-by: epenet <[email protected]>

* fix ordering of area

* update order alphabetically

* fix broken test

* update test_init

* Update homeassistant/const.py

Co-authored-by: epenet <[email protected]>

* 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 <[email protected]>
  • Loading branch information
mikey0000 and epenet authored Nov 21, 2024
1 parent 9add3a6 commit d854940
Show file tree
Hide file tree
Showing 29 changed files with 394 additions and 47 deletions.
6 changes: 3 additions & 3 deletions homeassistant/components/ecovacs/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
SensorStateClass,
)
from homeassistant.const import (
AREA_SQUARE_METERS,
ATTR_BATTERY_LEVEL,
CONF_DESCRIPTION,
PERCENTAGE,
EntityCategory,
UnitOfArea,
UnitOfTime,
)
from homeassistant.core import HomeAssistant
Expand Down Expand Up @@ -67,7 +67,7 @@ class EcovacsSensorEntityDescription(
capability_fn=lambda caps: caps.stats.clean,
value_fn=lambda e: e.area,
translation_key="stats_area",
native_unit_of_measurement=AREA_SQUARE_METERS,
native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
),
EcovacsSensorEntityDescription[StatsEvent](
key="stats_time",
Expand All @@ -84,7 +84,7 @@ class EcovacsSensorEntityDescription(
value_fn=lambda e: e.area,
key="total_stats_area",
translation_key="total_stats_area",
native_unit_of_measurement=AREA_SQUARE_METERS,
native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
state_class=SensorStateClass.TOTAL_INCREASING,
),
EcovacsSensorEntityDescription[TotalStatsEvent](
Expand Down
8 changes: 8 additions & 0 deletions homeassistant/components/number/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
SIGNAL_STRENGTH_DECIBELS,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
UnitOfApparentPower,
UnitOfArea,
UnitOfBloodGlucoseConcentration,
UnitOfConductivity,
UnitOfDataRate,
Expand Down Expand Up @@ -98,6 +99,12 @@ class NumberDeviceClass(StrEnum):
Unit of measurement: `None`
"""

AREA = "area"
"""Area
Unit of measurement: `UnitOfArea` units
"""

ATMOSPHERIC_PRESSURE = "atmospheric_pressure"
"""Atmospheric pressure.
Expand Down Expand Up @@ -434,6 +441,7 @@ class NumberDeviceClass(StrEnum):
DEVICE_CLASS_UNITS: dict[NumberDeviceClass, set[type[StrEnum] | str | None]] = {
NumberDeviceClass.APPARENT_POWER: set(UnitOfApparentPower),
NumberDeviceClass.AQI: {None},
NumberDeviceClass.AREA: set(UnitOfArea),
NumberDeviceClass.ATMOSPHERIC_PRESSURE: set(UnitOfPressure),
NumberDeviceClass.BATTERY: {PERCENTAGE},
NumberDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: set(UnitOfBloodGlucoseConcentration),
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/number/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
"aqi": {
"default": "mdi:air-filter"
},
"area": {
"default": "mdi:texture-box"
},
"atmospheric_pressure": {
"default": "mdi:thermometer-lines"
},
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/number/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"aqi": {
"name": "[%key:component::sensor::entity_component::aqi::name%]"
},
"area": {
"name": "[%key:component::sensor::entity_component::area::name%]"
},
"atmospheric_pressure": {
"name": "[%key:component::sensor::entity_component::atmospheric_pressure::name%]"
},
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/recorder/statistics.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from homeassistant.helpers.typing import UNDEFINED, UndefinedType
from homeassistant.util import dt as dt_util
from homeassistant.util.unit_conversion import (
AreaConverter,
BaseUnitConverter,
BloodGlucoseConcentrationConverter,
ConductivityConverter,
Expand Down Expand Up @@ -129,6 +130,7 @@


STATISTIC_UNIT_TO_UNIT_CONVERTER: dict[str | None, type[BaseUnitConverter]] = {
**{unit: AreaConverter for unit in AreaConverter.VALID_UNITS},
**{
unit: BloodGlucoseConcentrationConverter
for unit in BloodGlucoseConcentrationConverter.VALID_UNITS
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/recorder/websocket_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from homeassistant.helpers.json import json_bytes
from homeassistant.util import dt as dt_util
from homeassistant.util.unit_conversion import (
AreaConverter,
BloodGlucoseConcentrationConverter,
ConductivityConverter,
DataRateConverter,
Expand Down Expand Up @@ -55,6 +56,7 @@

UNIT_SCHEMA = vol.Schema(
{
vol.Optional("area"): vol.In(AreaConverter.VALID_UNITS),
vol.Optional("blood_glucose_concentration"): vol.In(
BloodGlucoseConcentrationConverter.VALID_UNITS
),
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/rituals_perfume_genie/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from homeassistant.components.select import SelectEntity, SelectEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import AREA_SQUARE_METERS, EntityCategory
from homeassistant.const import EntityCategory, UnitOfArea
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

Expand All @@ -30,7 +30,7 @@ class RitualsSelectEntityDescription(SelectEntityDescription):
RitualsSelectEntityDescription(
key="room_size_square_meter",
translation_key="room_size_square_meter",
unit_of_measurement=AREA_SQUARE_METERS,
unit_of_measurement=UnitOfArea.SQUARE_METERS,
entity_category=EntityCategory.CONFIG,
options=["15", "30", "60", "100"],
current_fn=lambda diffuser: str(diffuser.room_size_square_meter),
Expand Down
11 changes: 3 additions & 8 deletions homeassistant/components/roborock/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@
SensorEntity,
SensorEntityDescription,
)
from homeassistant.const import (
AREA_SQUARE_METERS,
PERCENTAGE,
EntityCategory,
UnitOfTime,
)
from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfArea, UnitOfTime
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
Expand Down Expand Up @@ -131,14 +126,14 @@ def _dock_error_value_fn(properties: DeviceProp) -> str | None:
translation_key="cleaning_area",
value_fn=lambda data: data.status.square_meter_clean_area,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=AREA_SQUARE_METERS,
native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
),
RoborockSensorDescription(
key="total_cleaning_area",
translation_key="total_cleaning_area",
value_fn=lambda data: data.clean_summary.square_meter_clean_area,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=AREA_SQUARE_METERS,
native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
),
RoborockSensorDescription(
key="vacuum_error",
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/romy/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
AREA_SQUARE_METERS,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfArea,
UnitOfLength,
UnitOfTime,
)
Expand Down Expand Up @@ -61,7 +61,7 @@
key="total_area_cleaned",
translation_key="total_area_cleaned",
state_class=SensorStateClass.TOTAL,
native_unit_of_measurement=AREA_SQUARE_METERS,
native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
entity_category=EntityCategory.DIAGNOSTIC,
),
SensorEntityDescription(
Expand Down
9 changes: 2 additions & 7 deletions homeassistant/components/roomba/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,7 @@
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
AREA_SQUARE_METERS,
PERCENTAGE,
EntityCategory,
UnitOfTime,
)
from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfArea, UnitOfTime
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
Expand Down Expand Up @@ -108,7 +103,7 @@ class RoombaSensorEntityDescription(SensorEntityDescription):
RoombaSensorEntityDescription(
key="total_cleaned_area",
translation_key="total_cleaned_area",
native_unit_of_measurement=AREA_SQUARE_METERS,
native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda self: (
None if (sqft := self.run_stats.get("sqft")) is None else sqft * 9.29
Expand Down
11 changes: 11 additions & 0 deletions homeassistant/components/sensor/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
SIGNAL_STRENGTH_DECIBELS,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
UnitOfApparentPower,
UnitOfArea,
UnitOfBloodGlucoseConcentration,
UnitOfConductivity,
UnitOfDataRate,
Expand Down Expand Up @@ -47,6 +48,7 @@
dir_with_deprecated_constants,
)
from homeassistant.util.unit_conversion import (
AreaConverter,
BaseUnitConverter,
BloodGlucoseConcentrationConverter,
ConductivityConverter,
Expand Down Expand Up @@ -117,6 +119,12 @@ class SensorDeviceClass(StrEnum):
Unit of measurement: `None`
"""

AREA = "area"
"""Area
Unit of measurement: `UnitOfArea` units
"""

ATMOSPHERIC_PRESSURE = "atmospheric_pressure"
"""Atmospheric pressure.
Expand Down Expand Up @@ -500,6 +508,7 @@ class SensorStateClass(StrEnum):
STATE_CLASSES: Final[list[str]] = [cls.value for cls in SensorStateClass]

UNIT_CONVERTERS: dict[SensorDeviceClass | str | None, type[BaseUnitConverter]] = {
SensorDeviceClass.AREA: AreaConverter,
SensorDeviceClass.ATMOSPHERIC_PRESSURE: PressureConverter,
SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: BloodGlucoseConcentrationConverter,
SensorDeviceClass.CONDUCTIVITY: ConductivityConverter,
Expand Down Expand Up @@ -531,6 +540,7 @@ class SensorStateClass(StrEnum):
DEVICE_CLASS_UNITS: dict[SensorDeviceClass, set[type[StrEnum] | str | None]] = {
SensorDeviceClass.APPARENT_POWER: set(UnitOfApparentPower),
SensorDeviceClass.AQI: {None},
SensorDeviceClass.AREA: set(UnitOfArea),
SensorDeviceClass.ATMOSPHERIC_PRESSURE: set(UnitOfPressure),
SensorDeviceClass.BATTERY: {PERCENTAGE},
SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: set(UnitOfBloodGlucoseConcentration),
Expand Down Expand Up @@ -607,6 +617,7 @@ class SensorStateClass(StrEnum):
DEVICE_CLASS_STATE_CLASSES: dict[SensorDeviceClass, set[SensorStateClass]] = {
SensorDeviceClass.APPARENT_POWER: {SensorStateClass.MEASUREMENT},
SensorDeviceClass.AQI: {SensorStateClass.MEASUREMENT},
SensorDeviceClass.AREA: set(SensorStateClass),
SensorDeviceClass.ATMOSPHERIC_PRESSURE: {SensorStateClass.MEASUREMENT},
SensorDeviceClass.BATTERY: {SensorStateClass.MEASUREMENT},
SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: {SensorStateClass.MEASUREMENT},
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/sensor/device_condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

CONF_IS_APPARENT_POWER = "is_apparent_power"
CONF_IS_AQI = "is_aqi"
CONF_IS_AREA = "is_area"
CONF_IS_ATMOSPHERIC_PRESSURE = "is_atmospheric_pressure"
CONF_IS_BATTERY_LEVEL = "is_battery_level"
CONF_IS_BLOOD_GLUCOSE_CONCENTRATION = "is_blood_glucose_concentration"
Expand Down Expand Up @@ -86,6 +87,7 @@
ENTITY_CONDITIONS = {
SensorDeviceClass.APPARENT_POWER: [{CONF_TYPE: CONF_IS_APPARENT_POWER}],
SensorDeviceClass.AQI: [{CONF_TYPE: CONF_IS_AQI}],
SensorDeviceClass.AREA: [{CONF_TYPE: CONF_IS_AREA}],
SensorDeviceClass.ATMOSPHERIC_PRESSURE: [{CONF_TYPE: CONF_IS_ATMOSPHERIC_PRESSURE}],
SensorDeviceClass.BATTERY: [{CONF_TYPE: CONF_IS_BATTERY_LEVEL}],
SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: [
Expand Down Expand Up @@ -153,6 +155,7 @@
[
CONF_IS_APPARENT_POWER,
CONF_IS_AQI,
CONF_IS_AREA,
CONF_IS_ATMOSPHERIC_PRESSURE,
CONF_IS_BATTERY_LEVEL,
CONF_IS_BLOOD_GLUCOSE_CONCENTRATION,
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/sensor/device_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

CONF_APPARENT_POWER = "apparent_power"
CONF_AQI = "aqi"
CONF_AREA = "area"
CONF_ATMOSPHERIC_PRESSURE = "atmospheric_pressure"
CONF_BATTERY_LEVEL = "battery_level"
CONF_BLOOD_GLUCOSE_CONCENTRATION = "blood_glucose_concentration"
Expand Down Expand Up @@ -85,6 +86,7 @@
ENTITY_TRIGGERS = {
SensorDeviceClass.APPARENT_POWER: [{CONF_TYPE: CONF_APPARENT_POWER}],
SensorDeviceClass.AQI: [{CONF_TYPE: CONF_AQI}],
SensorDeviceClass.AREA: [{CONF_TYPE: CONF_AREA}],
SensorDeviceClass.ATMOSPHERIC_PRESSURE: [{CONF_TYPE: CONF_ATMOSPHERIC_PRESSURE}],
SensorDeviceClass.BATTERY: [{CONF_TYPE: CONF_BATTERY_LEVEL}],
SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: [
Expand Down Expand Up @@ -153,6 +155,7 @@
[
CONF_APPARENT_POWER,
CONF_AQI,
CONF_AREA,
CONF_ATMOSPHERIC_PRESSURE,
CONF_BATTERY_LEVEL,
CONF_BLOOD_GLUCOSE_CONCENTRATION,
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/sensor/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
"aqi": {
"default": "mdi:air-filter"
},
"area": {
"default": "mdi:texture-box"
},
"atmospheric_pressure": {
"default": "mdi:thermometer-lines"
},
Expand Down
5 changes: 5 additions & 0 deletions homeassistant/components/sensor/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"condition_type": {
"is_apparent_power": "Current {entity_name} apparent power",
"is_aqi": "Current {entity_name} air quality index",
"is_area": "Current {entity_name} area",
"is_atmospheric_pressure": "Current {entity_name} atmospheric pressure",
"is_battery_level": "Current {entity_name} battery level",
"is_blood_glucose_concentration": "Current {entity_name} blood glucose concentration",
Expand Down Expand Up @@ -55,6 +56,7 @@
"trigger_type": {
"apparent_power": "{entity_name} apparent power changes",
"aqi": "{entity_name} air quality index changes",
"area": "{entity_name} area changes",
"atmospheric_pressure": "{entity_name} atmospheric pressure changes",
"battery_level": "{entity_name} battery level changes",
"blood_glucose_concentration": "{entity_name} blood glucose concentration changes",
Expand Down Expand Up @@ -145,6 +147,9 @@
"aqi": {
"name": "Air quality index"
},
"area": {
"name": "Area"
},
"atmospheric_pressure": {
"name": "Atmospheric pressure"
},
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/smartthings/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
AREA_SQUARE_METERS,
CONCENTRATION_PARTS_PER_MILLION,
LIGHT_LUX,
PERCENTAGE,
EntityCategory,
UnitOfArea,
UnitOfElectricPotential,
UnitOfEnergy,
UnitOfMass,
Expand Down Expand Up @@ -95,7 +95,7 @@ class Map(NamedTuple):
Map(
Attribute.bmi_measurement,
"Body Mass Index",
f"{UnitOfMass.KILOGRAMS}/{AREA_SQUARE_METERS}",
f"{UnitOfMass.KILOGRAMS}/{UnitOfArea.SQUARE_METERS}",
None,
SensorStateClass.MEASUREMENT,
None,
Expand Down
Loading

0 comments on commit d854940

Please sign in to comment.