Support all Energy units in Energy integration (#148566)

This commit is contained in:
karwosts 2025-07-10 11:29:48 -07:00 committed by GitHub
parent d15baf9f9f
commit f0a636949a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 26 additions and 42 deletions

View File

@ -41,13 +41,8 @@ SUPPORTED_STATE_CLASSES = {
SensorStateClass.TOTAL,
SensorStateClass.TOTAL_INCREASING,
}
VALID_ENERGY_UNITS: set[str] = {
UnitOfEnergy.GIGA_JOULE,
UnitOfEnergy.KILO_WATT_HOUR,
UnitOfEnergy.MEGA_JOULE,
UnitOfEnergy.MEGA_WATT_HOUR,
UnitOfEnergy.WATT_HOUR,
}
VALID_ENERGY_UNITS: set[str] = set(UnitOfEnergy)
VALID_ENERGY_UNITS_GAS = {
UnitOfVolume.CENTUM_CUBIC_FEET,
UnitOfVolume.CUBIC_FEET,

View File

@ -21,14 +21,9 @@ from .const import DOMAIN
ENERGY_USAGE_DEVICE_CLASSES = (sensor.SensorDeviceClass.ENERGY,)
ENERGY_USAGE_UNITS: dict[str, tuple[UnitOfEnergy, ...]] = {
sensor.SensorDeviceClass.ENERGY: (
UnitOfEnergy.GIGA_JOULE,
UnitOfEnergy.KILO_WATT_HOUR,
UnitOfEnergy.MEGA_JOULE,
UnitOfEnergy.MEGA_WATT_HOUR,
UnitOfEnergy.WATT_HOUR,
)
sensor.SensorDeviceClass.ENERGY: tuple(UnitOfEnergy)
}
ENERGY_PRICE_UNITS = tuple(
f"/{unit}" for units in ENERGY_USAGE_UNITS.values() for unit in units
)
@ -39,13 +34,9 @@ GAS_USAGE_DEVICE_CLASSES = (
sensor.SensorDeviceClass.GAS,
)
GAS_USAGE_UNITS: dict[str, tuple[UnitOfEnergy | UnitOfVolume, ...]] = {
sensor.SensorDeviceClass.ENERGY: (
UnitOfEnergy.GIGA_JOULE,
UnitOfEnergy.KILO_WATT_HOUR,
UnitOfEnergy.MEGA_JOULE,
UnitOfEnergy.MEGA_WATT_HOUR,
UnitOfEnergy.WATT_HOUR,
),
sensor.SensorDeviceClass.ENERGY: ENERGY_USAGE_UNITS[
sensor.SensorDeviceClass.ENERGY
],
sensor.SensorDeviceClass.GAS: (
UnitOfVolume.CENTUM_CUBIC_FEET,
UnitOfVolume.CUBIC_FEET,

View File

@ -29,6 +29,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from homeassistant.util.unit_conversion import _WH_TO_CAL, _WH_TO_J
from homeassistant.util.unit_system import METRIC_SYSTEM, US_CUSTOMARY_SYSTEM
from tests.components.recorder.common import async_wait_recording_done
@ -748,10 +749,12 @@ async def test_cost_sensor_price_entity_total_no_reset(
@pytest.mark.parametrize(
("energy_unit", "factor"),
[
(UnitOfEnergy.MILLIWATT_HOUR, 1e6),
(UnitOfEnergy.WATT_HOUR, 1000),
(UnitOfEnergy.KILO_WATT_HOUR, 1),
(UnitOfEnergy.MEGA_WATT_HOUR, 0.001),
(UnitOfEnergy.GIGA_JOULE, 0.001 * 3.6),
(UnitOfEnergy.GIGA_JOULE, _WH_TO_J / 1e6),
(UnitOfEnergy.CALORIE, _WH_TO_CAL * 1e3),
],
)
async def test_cost_sensor_handle_energy_units(
@ -815,6 +818,7 @@ async def test_cost_sensor_handle_energy_units(
@pytest.mark.parametrize(
("price_unit", "factor"),
[
(f"EUR/{UnitOfEnergy.MILLIWATT_HOUR}", 1e-6),
(f"EUR/{UnitOfEnergy.WATT_HOUR}", 0.001),
(f"EUR/{UnitOfEnergy.KILO_WATT_HOUR}", 1),
(f"EUR/{UnitOfEnergy.MEGA_WATT_HOUR}", 1000),

View File

@ -12,6 +12,10 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.json import JSON_DUMP
from homeassistant.setup import async_setup_component
ENERGY_UNITS_STRING = ", ".join(tuple(UnitOfEnergy))
ENERGY_PRICE_UNITS_STRING = ", ".join(f"EUR/{unit}" for unit in tuple(UnitOfEnergy))
@pytest.fixture
def mock_is_entity_recorded():
@ -69,6 +73,7 @@ async def test_validation_empty_config(hass: HomeAssistant) -> None:
@pytest.mark.parametrize(
("state_class", "energy_unit", "extra"),
[
("total_increasing", UnitOfEnergy.MILLIWATT_HOUR, {}),
("total_increasing", UnitOfEnergy.KILO_WATT_HOUR, {}),
("total_increasing", UnitOfEnergy.MEGA_WATT_HOUR, {}),
("total_increasing", UnitOfEnergy.WATT_HOUR, {}),
@ -76,6 +81,7 @@ async def test_validation_empty_config(hass: HomeAssistant) -> None:
("total", UnitOfEnergy.KILO_WATT_HOUR, {"last_reset": "abc"}),
("measurement", UnitOfEnergy.KILO_WATT_HOUR, {"last_reset": "abc"}),
("total_increasing", UnitOfEnergy.GIGA_JOULE, {}),
("total_increasing", UnitOfEnergy.CALORIE, {}),
],
)
async def test_validation(
@ -235,9 +241,7 @@ async def test_validation_device_consumption_entity_unexpected_unit(
{
"type": "entity_unexpected_unit_energy",
"affected_entities": {("sensor.unexpected_unit", "beers")},
"translation_placeholders": {
"energy_units": "GJ, kWh, MJ, MWh, Wh"
},
"translation_placeholders": {"energy_units": ENERGY_UNITS_STRING},
}
]
],
@ -325,9 +329,7 @@ async def test_validation_solar(
{
"type": "entity_unexpected_unit_energy",
"affected_entities": {("sensor.solar_production", "beers")},
"translation_placeholders": {
"energy_units": "GJ, kWh, MJ, MWh, Wh"
},
"translation_placeholders": {"energy_units": ENERGY_UNITS_STRING},
}
]
],
@ -378,9 +380,7 @@ async def test_validation_battery(
("sensor.battery_import", "beers"),
("sensor.battery_export", "beers"),
},
"translation_placeholders": {
"energy_units": "GJ, kWh, MJ, MWh, Wh"
},
"translation_placeholders": {"energy_units": ENERGY_UNITS_STRING},
},
]
],
@ -449,9 +449,7 @@ async def test_validation_grid(
("sensor.grid_consumption_1", "beers"),
("sensor.grid_production_1", "beers"),
},
"translation_placeholders": {
"energy_units": "GJ, kWh, MJ, MWh, Wh"
},
"translation_placeholders": {"energy_units": ENERGY_UNITS_STRING},
},
{
"type": "statistics_not_defined",
@ -538,9 +536,7 @@ async def test_validation_grid_external_cost_compensation(
("sensor.grid_consumption_1", "beers"),
("sensor.grid_production_1", "beers"),
},
"translation_placeholders": {
"energy_units": "GJ, kWh, MJ, MWh, Wh"
},
"translation_placeholders": {"energy_units": ENERGY_UNITS_STRING},
},
{
"type": "statistics_not_defined",
@ -710,9 +706,7 @@ async def test_validation_grid_auto_cost_entity_errors(
{
"type": "entity_unexpected_unit_energy_price",
"affected_entities": {("sensor.grid_price_1", "$/Ws")},
"translation_placeholders": {
"price_units": "EUR/GJ, EUR/kWh, EUR/MJ, EUR/MWh, EUR/Wh"
},
"translation_placeholders": {"price_units": ENERGY_PRICE_UNITS_STRING},
},
),
],
@ -855,7 +849,7 @@ async def test_validation_gas(
"type": "entity_unexpected_unit_gas",
"affected_entities": {("sensor.gas_consumption_1", "beers")},
"translation_placeholders": {
"energy_units": "GJ, kWh, MJ, MWh, Wh",
"energy_units": ENERGY_UNITS_STRING,
"gas_units": "CCF, ft³, m³, L",
},
},
@ -885,7 +879,7 @@ async def test_validation_gas(
"affected_entities": {("sensor.gas_price_2", "EUR/invalid")},
"translation_placeholders": {
"price_units": (
"EUR/GJ, EUR/kWh, EUR/MJ, EUR/MWh, EUR/Wh, EUR/CCF, EUR/ft³, EUR/m³, EUR/L"
f"{ENERGY_PRICE_UNITS_STRING}, EUR/CCF, EUR/ft³, EUR/m³, EUR/L"
)
},
},