From dcd7830a35d627d1ac1ea49996fb04f635f08baa Mon Sep 17 00:00:00 2001 From: Sergey Dudanov Date: Tue, 10 Sep 2024 14:22:15 +0400 Subject: [PATCH] Add calories to energy sensor device class (#122796) * added calories to energy class * changes * temporarily solving the problem with conversion accuracy * add tests * added calories to energy class * changes * add tests * Update homeassistant/util/unit_conversion.py Co-authored-by: Robert Resch * Update homeassistant/util/unit_conversion.py Co-authored-by: Robert Resch * apply suggestions * Update homeassistant/util/unit_conversion.py --------- Co-authored-by: Robert Resch Co-authored-by: Erik Montnemery --- homeassistant/components/sensor/const.py | 2 +- homeassistant/const.py | 12 ++++++--- homeassistant/util/unit_conversion.py | 26 +++++++++++-------- tests/components/template/test_config_flow.py | 2 +- tests/util/test_unit_conversion.py | 20 +++++++++++--- 5 files changed, 42 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/sensor/const.py b/homeassistant/components/sensor/const.py index 8f63e346caf..de30678d9fa 100644 --- a/homeassistant/components/sensor/const.py +++ b/homeassistant/components/sensor/const.py @@ -182,7 +182,7 @@ class SensorDeviceClass(StrEnum): Use this device class for sensors measuring energy consumption, for example electric energy consumption. - Unit of measurement: `Wh`, `kWh`, `MWh`, `MJ`, `GJ` + Unit of measurement: `J`, `kJ`, `MJ`, `GJ`, `Wh`, `kWh`, `MWh`, `cal`, `kcal`, `Mcal`, `Gcal` """ ENERGY_STORAGE = "energy_storage" diff --git a/homeassistant/const.py b/homeassistant/const.py index 45d6a97885b..acbef5c58cc 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -693,11 +693,17 @@ _DEPRECATED_POWER_VOLT_AMPERE_REACTIVE: Final = DeprecatedConstantEnum( class UnitOfEnergy(StrEnum): """Energy units.""" - GIGA_JOULE = "GJ" - KILO_WATT_HOUR = "kWh" + JOULE = "J" + KILO_JOULE = "kJ" MEGA_JOULE = "MJ" - MEGA_WATT_HOUR = "MWh" + GIGA_JOULE = "GJ" WATT_HOUR = "Wh" + KILO_WATT_HOUR = "kWh" + MEGA_WATT_HOUR = "MWh" + CALORIE = "cal" + KILO_CALORIE = "kcal" + MEGA_CALORIE = "Mcal" + GIGA_CALORIE = "Gcal" _DEPRECATED_ENERGY_KILO_WATT_HOUR: Final = DeprecatedConstantEnum( diff --git a/homeassistant/util/unit_conversion.py b/homeassistant/util/unit_conversion.py index d5586704fc5..dd6d300a2c1 100644 --- a/homeassistant/util/unit_conversion.py +++ b/homeassistant/util/unit_conversion.py @@ -47,6 +47,10 @@ _HRS_TO_MINUTES = 60 # 1 hr = 60 minutes _HRS_TO_SECS = _HRS_TO_MINUTES * _MIN_TO_SEC # 1 hr = 60 minutes = 3600 seconds _DAYS_TO_SECS = 24 * _HRS_TO_SECS # 1 day = 24 hours = 86400 seconds +# Energy conversion constants +_WH_TO_J = 3600 # 1 Wh = 3600 J +_WH_TO_CAL = _WH_TO_J / 4.184 # 1 Wh = 860.42065 cal + # Mass conversion constants _POUND_TO_G = 453.59237 _OUNCE_TO_G = _POUND_TO_G / 16 # 16 ounces to a pound @@ -209,19 +213,19 @@ class EnergyConverter(BaseUnitConverter): UNIT_CLASS = "energy" _UNIT_CONVERSION: dict[str | None, float] = { - UnitOfEnergy.WATT_HOUR: 1 * 1000, + UnitOfEnergy.JOULE: _WH_TO_J * 1e3, + UnitOfEnergy.KILO_JOULE: _WH_TO_J, + UnitOfEnergy.MEGA_JOULE: _WH_TO_J / 1e3, + UnitOfEnergy.GIGA_JOULE: _WH_TO_J / 1e6, + UnitOfEnergy.WATT_HOUR: 1e3, UnitOfEnergy.KILO_WATT_HOUR: 1, - UnitOfEnergy.MEGA_WATT_HOUR: 1 / 1000, - UnitOfEnergy.MEGA_JOULE: 3.6, - UnitOfEnergy.GIGA_JOULE: 3.6 / 1000, - } - VALID_UNITS = { - UnitOfEnergy.WATT_HOUR, - UnitOfEnergy.KILO_WATT_HOUR, - UnitOfEnergy.MEGA_WATT_HOUR, - UnitOfEnergy.MEGA_JOULE, - UnitOfEnergy.GIGA_JOULE, + UnitOfEnergy.MEGA_WATT_HOUR: 1 / 1e3, + UnitOfEnergy.CALORIE: _WH_TO_CAL * 1e3, + UnitOfEnergy.KILO_CALORIE: _WH_TO_CAL, + UnitOfEnergy.MEGA_CALORIE: _WH_TO_CAL / 1e3, + UnitOfEnergy.GIGA_CALORIE: _WH_TO_CAL / 1e6, } + VALID_UNITS = set(UnitOfEnergy) class InformationConverter(BaseUnitConverter): diff --git a/tests/components/template/test_config_flow.py b/tests/components/template/test_config_flow.py index eb2c6e57f85..9a89d72dc2e 100644 --- a/tests/components/template/test_config_flow.py +++ b/tests/components/template/test_config_flow.py @@ -764,7 +764,7 @@ EARLY_END_ERROR = "invalid template (TemplateSyntaxError: unexpected 'end of tem ), "unit_of_measurement": ( "'None' is not a valid unit for device class 'energy'; " - "expected one of 'GJ', 'kWh', 'MJ', 'MWh', 'Wh'" + "expected one of 'cal', 'Gcal', 'GJ', 'J', 'kcal', 'kJ', 'kWh', 'Mcal', 'MJ', 'MWh', 'Wh'" ), }, ), diff --git a/tests/util/test_unit_conversion.py b/tests/util/test_unit_conversion.py index 98a6a1da5a6..8342aa732f8 100644 --- a/tests/util/test_unit_conversion.py +++ b/tests/util/test_unit_conversion.py @@ -282,10 +282,22 @@ _CONVERTED_VALUE: dict[ (10, UnitOfEnergy.KILO_WATT_HOUR, 0.01, UnitOfEnergy.MEGA_WATT_HOUR), (10, UnitOfEnergy.MEGA_WATT_HOUR, 10000000, UnitOfEnergy.WATT_HOUR), (10, UnitOfEnergy.MEGA_WATT_HOUR, 10000, UnitOfEnergy.KILO_WATT_HOUR), - (10, UnitOfEnergy.GIGA_JOULE, 10000 / 3.6, UnitOfEnergy.KILO_WATT_HOUR), - (10, UnitOfEnergy.GIGA_JOULE, 10 / 3.6, UnitOfEnergy.MEGA_WATT_HOUR), - (10, UnitOfEnergy.MEGA_JOULE, 10 / 3.6, UnitOfEnergy.KILO_WATT_HOUR), - (10, UnitOfEnergy.MEGA_JOULE, 0.010 / 3.6, UnitOfEnergy.MEGA_WATT_HOUR), + (10, UnitOfEnergy.GIGA_JOULE, 2777.78, UnitOfEnergy.KILO_WATT_HOUR), + (10, UnitOfEnergy.GIGA_JOULE, 2.77778, UnitOfEnergy.MEGA_WATT_HOUR), + (10, UnitOfEnergy.MEGA_JOULE, 2.77778, UnitOfEnergy.KILO_WATT_HOUR), + (10, UnitOfEnergy.MEGA_JOULE, 2.77778e-3, UnitOfEnergy.MEGA_WATT_HOUR), + (10, UnitOfEnergy.KILO_JOULE, 2.77778, UnitOfEnergy.WATT_HOUR), + (10, UnitOfEnergy.KILO_JOULE, 2.77778e-6, UnitOfEnergy.MEGA_WATT_HOUR), + (10, UnitOfEnergy.JOULE, 2.77778e-3, UnitOfEnergy.WATT_HOUR), + (10, UnitOfEnergy.JOULE, 2.390057, UnitOfEnergy.CALORIE), + (10, UnitOfEnergy.CALORIE, 0.01, UnitOfEnergy.KILO_CALORIE), + (10, UnitOfEnergy.CALORIE, 0.011622222, UnitOfEnergy.WATT_HOUR), + (10, UnitOfEnergy.KILO_CALORIE, 0.01, UnitOfEnergy.MEGA_CALORIE), + (10, UnitOfEnergy.KILO_CALORIE, 0.011622222, UnitOfEnergy.KILO_WATT_HOUR), + (10, UnitOfEnergy.MEGA_CALORIE, 0.01, UnitOfEnergy.GIGA_CALORIE), + (10, UnitOfEnergy.MEGA_CALORIE, 0.011622222, UnitOfEnergy.MEGA_WATT_HOUR), + (10, UnitOfEnergy.GIGA_CALORIE, 10000, UnitOfEnergy.MEGA_CALORIE), + (10, UnitOfEnergy.GIGA_CALORIE, 11.622222, UnitOfEnergy.MEGA_WATT_HOUR), ], InformationConverter: [ (8e3, UnitOfInformation.BITS, 8, UnitOfInformation.KILOBITS),