Fix gas validation (#55886)
parent
efafe82799
commit
ec337101dd
homeassistant/components/energy
tests/components/energy
|
@ -1,6 +1,7 @@
|
|||
"""Validate the energy preferences provide valid data."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Sequence
|
||||
import dataclasses
|
||||
from typing import Any
|
||||
|
||||
|
@ -10,12 +11,24 @@ from homeassistant.const import (
|
|||
ENERGY_WATT_HOUR,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
VOLUME_CUBIC_FEET,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback, valid_entity_id
|
||||
|
||||
from . import data
|
||||
from .const import DOMAIN
|
||||
|
||||
ENERGY_USAGE_UNITS = (ENERGY_KILO_WATT_HOUR, ENERGY_WATT_HOUR)
|
||||
ENERGY_UNIT_ERROR = "entity_unexpected_unit_energy"
|
||||
GAS_USAGE_UNITS = (
|
||||
ENERGY_WATT_HOUR,
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
VOLUME_CUBIC_METERS,
|
||||
VOLUME_CUBIC_FEET,
|
||||
)
|
||||
GAS_UNIT_ERROR = "entity_unexpected_unit_gas"
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class ValidationIssue:
|
||||
|
@ -43,8 +56,12 @@ class EnergyPreferencesValidation:
|
|||
|
||||
|
||||
@callback
|
||||
def _async_validate_energy_stat(
|
||||
hass: HomeAssistant, stat_value: str, result: list[ValidationIssue]
|
||||
def _async_validate_usage_stat(
|
||||
hass: HomeAssistant,
|
||||
stat_value: str,
|
||||
allowed_units: Sequence[str],
|
||||
unit_error: str,
|
||||
result: list[ValidationIssue],
|
||||
) -> None:
|
||||
"""Validate a statistic."""
|
||||
has_entity_source = valid_entity_id(stat_value)
|
||||
|
@ -91,10 +108,8 @@ def _async_validate_energy_stat(
|
|||
|
||||
unit = state.attributes.get("unit_of_measurement")
|
||||
|
||||
if unit not in (ENERGY_KILO_WATT_HOUR, ENERGY_WATT_HOUR):
|
||||
result.append(
|
||||
ValidationIssue("entity_unexpected_unit_energy", stat_value, unit)
|
||||
)
|
||||
if unit not in allowed_units:
|
||||
result.append(ValidationIssue(unit_error, stat_value, unit))
|
||||
|
||||
state_class = state.attributes.get("state_class")
|
||||
|
||||
|
@ -211,8 +226,12 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
|
|||
|
||||
if source["type"] == "grid":
|
||||
for flow in source["flow_from"]:
|
||||
_async_validate_energy_stat(
|
||||
hass, flow["stat_energy_from"], source_result
|
||||
_async_validate_usage_stat(
|
||||
hass,
|
||||
flow["stat_energy_from"],
|
||||
ENERGY_USAGE_UNITS,
|
||||
ENERGY_UNIT_ERROR,
|
||||
source_result,
|
||||
)
|
||||
|
||||
if flow.get("stat_cost") is not None:
|
||||
|
@ -229,7 +248,13 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
|
|||
)
|
||||
|
||||
for flow in source["flow_to"]:
|
||||
_async_validate_energy_stat(hass, flow["stat_energy_to"], source_result)
|
||||
_async_validate_usage_stat(
|
||||
hass,
|
||||
flow["stat_energy_to"],
|
||||
ENERGY_USAGE_UNITS,
|
||||
ENERGY_UNIT_ERROR,
|
||||
source_result,
|
||||
)
|
||||
|
||||
if flow.get("stat_compensation") is not None:
|
||||
_async_validate_cost_stat(
|
||||
|
@ -247,7 +272,13 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
|
|||
)
|
||||
|
||||
elif source["type"] == "gas":
|
||||
_async_validate_energy_stat(hass, source["stat_energy_from"], source_result)
|
||||
_async_validate_usage_stat(
|
||||
hass,
|
||||
source["stat_energy_from"],
|
||||
GAS_USAGE_UNITS,
|
||||
GAS_UNIT_ERROR,
|
||||
source_result,
|
||||
)
|
||||
|
||||
if source.get("stat_cost") is not None:
|
||||
_async_validate_cost_stat(hass, source["stat_cost"], source_result)
|
||||
|
@ -263,15 +294,39 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
|
|||
)
|
||||
|
||||
elif source["type"] == "solar":
|
||||
_async_validate_energy_stat(hass, source["stat_energy_from"], source_result)
|
||||
_async_validate_usage_stat(
|
||||
hass,
|
||||
source["stat_energy_from"],
|
||||
ENERGY_USAGE_UNITS,
|
||||
ENERGY_UNIT_ERROR,
|
||||
source_result,
|
||||
)
|
||||
|
||||
elif source["type"] == "battery":
|
||||
_async_validate_energy_stat(hass, source["stat_energy_from"], source_result)
|
||||
_async_validate_energy_stat(hass, source["stat_energy_to"], source_result)
|
||||
_async_validate_usage_stat(
|
||||
hass,
|
||||
source["stat_energy_from"],
|
||||
ENERGY_USAGE_UNITS,
|
||||
ENERGY_UNIT_ERROR,
|
||||
source_result,
|
||||
)
|
||||
_async_validate_usage_stat(
|
||||
hass,
|
||||
source["stat_energy_to"],
|
||||
ENERGY_USAGE_UNITS,
|
||||
ENERGY_UNIT_ERROR,
|
||||
source_result,
|
||||
)
|
||||
|
||||
for device in manager.data["device_consumption"]:
|
||||
device_result: list[ValidationIssue] = []
|
||||
result.device_consumption.append(device_result)
|
||||
_async_validate_energy_stat(hass, device["stat_consumption"], device_result)
|
||||
_async_validate_usage_stat(
|
||||
hass,
|
||||
device["stat_consumption"],
|
||||
ENERGY_USAGE_UNITS,
|
||||
ENERGY_UNIT_ERROR,
|
||||
device_result,
|
||||
)
|
||||
|
||||
return result
|
||||
|
|
|
@ -441,3 +441,59 @@ async def test_validation_grid_price_errors(
|
|||
],
|
||||
"device_consumption": [],
|
||||
}
|
||||
|
||||
|
||||
async def test_validation_gas(hass, mock_energy_manager, mock_is_entity_recorded):
|
||||
"""Test validating gas with sensors for energy and cost/compensation."""
|
||||
mock_is_entity_recorded["sensor.gas_cost_1"] = False
|
||||
mock_is_entity_recorded["sensor.gas_compensation_1"] = False
|
||||
await mock_energy_manager.async_update(
|
||||
{
|
||||
"energy_sources": [
|
||||
{
|
||||
"type": "gas",
|
||||
"stat_energy_from": "sensor.gas_consumption_1",
|
||||
"stat_cost": "sensor.gas_cost_1",
|
||||
},
|
||||
{
|
||||
"type": "gas",
|
||||
"stat_energy_from": "sensor.gas_consumption_2",
|
||||
"stat_cost": "sensor.gas_cost_2",
|
||||
},
|
||||
]
|
||||
}
|
||||
)
|
||||
hass.states.async_set(
|
||||
"sensor.gas_consumption_1",
|
||||
"10.10",
|
||||
{"unit_of_measurement": "beers", "state_class": "total_increasing"},
|
||||
)
|
||||
hass.states.async_set(
|
||||
"sensor.gas_consumption_2",
|
||||
"10.10",
|
||||
{"unit_of_measurement": "kWh", "state_class": "total_increasing"},
|
||||
)
|
||||
hass.states.async_set(
|
||||
"sensor.gas_cost_2",
|
||||
"10.10",
|
||||
{"unit_of_measurement": "EUR/kWh", "state_class": "total_increasing"},
|
||||
)
|
||||
|
||||
assert (await validate.async_validate(hass)).as_dict() == {
|
||||
"energy_sources": [
|
||||
[
|
||||
{
|
||||
"type": "entity_unexpected_unit_gas",
|
||||
"identifier": "sensor.gas_consumption_1",
|
||||
"value": "beers",
|
||||
},
|
||||
{
|
||||
"type": "recorder_untracked",
|
||||
"identifier": "sensor.gas_cost_1",
|
||||
"value": None,
|
||||
},
|
||||
],
|
||||
[],
|
||||
],
|
||||
"device_consumption": [],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue