Simplify energy settings (#78947)

This commit is contained in:
Erik Montnemery 2022-09-23 03:58:15 +02:00 committed by GitHub
parent 27599ea0ee
commit 6b0c9b6a6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 28 additions and 72 deletions

View File

@ -32,12 +32,11 @@ class FlowFromGridSourceType(TypedDict):
stat_energy_from: str
# statistic_id of costs ($) incurred from the energy meter
# If set to None and entity_energy_from and entity_energy_price are configured,
# If set to None and entity_energy_price or number_energy_price are configured,
# an EnergyCostSensor will be automatically created
stat_cost: str | None
# Used to generate costs if stat_cost is set to None
entity_energy_from: str | None # entity_id of an energy meter (kWh), entity_id of the energy meter for stat_energy_from
entity_energy_price: str | None # entity_id of an entity providing price ($/kWh)
number_energy_price: float | None # Price for energy ($/kWh)
@ -49,12 +48,11 @@ class FlowToGridSourceType(TypedDict):
stat_energy_to: str
# statistic_id of compensation ($) received for contributing back
# If set to None and entity_energy_from and entity_energy_price are configured,
# If set to None and entity_energy_price or number_energy_price are configured,
# an EnergyCostSensor will be automatically created
stat_compensation: str | None
# Used to generate costs if stat_compensation is set to None
entity_energy_to: str | None # entity_id of an energy meter (kWh), entity_id of the energy meter for stat_energy_to
entity_energy_price: str | None # entity_id of an entity providing price ($/kWh)
number_energy_price: float | None # Price for energy ($/kWh)
@ -96,12 +94,11 @@ class GasSourceType(TypedDict):
stat_energy_from: str
# statistic_id of costs ($) incurred from the energy meter
# If set to None and entity_energy_from and entity_energy_price are configured,
# If set to None and entity_energy_price or number_energy_price are configured,
# an EnergyCostSensor will be automatically created
stat_cost: str | None
# Used to generate costs if stat_cost is set to None
entity_energy_from: str | None # entity_id of an gas meter (m³), entity_id of the gas meter for stat_energy_from
entity_energy_price: str | None # entity_id of an entity providing price ($/m³)
number_energy_price: float | None # Price for energy ($/m³)
@ -145,7 +142,8 @@ FLOW_FROM_GRID_SOURCE_SCHEMA = vol.All(
{
vol.Required("stat_energy_from"): str,
vol.Optional("stat_cost"): vol.Any(str, None),
vol.Optional("entity_energy_from"): vol.Any(str, None),
# entity_energy_from was removed in HA Core 2022.10
vol.Remove("entity_energy_from"): vol.Any(str, None),
vol.Optional("entity_energy_price"): vol.Any(str, None),
vol.Optional("number_energy_price"): vol.Any(vol.Coerce(float), None),
}
@ -158,7 +156,8 @@ FLOW_TO_GRID_SOURCE_SCHEMA = vol.Schema(
{
vol.Required("stat_energy_to"): str,
vol.Optional("stat_compensation"): vol.Any(str, None),
vol.Optional("entity_energy_to"): vol.Any(str, None),
# entity_energy_to was removed in HA Core 2022.10
vol.Remove("entity_energy_to"): vol.Any(str, None),
vol.Optional("entity_energy_price"): vol.Any(str, None),
vol.Optional("number_energy_price"): vol.Any(vol.Coerce(float), None),
}
@ -216,7 +215,8 @@ GAS_SOURCE_SCHEMA = vol.Schema(
vol.Required("type"): "gas",
vol.Required("stat_energy_from"): str,
vol.Optional("stat_cost"): vol.Any(str, None),
vol.Optional("entity_energy_from"): vol.Any(str, None),
# entity_energy_from was removed in HA Core 2022.10
vol.Remove("entity_energy_from"): vol.Any(str, None),
vol.Optional("entity_energy_price"): vol.Any(str, None),
vol.Optional("number_energy_price"): vol.Any(vol.Coerce(float), None),
}

View File

@ -67,7 +67,6 @@ class SourceAdapter:
source_type: Literal["grid", "gas"]
flow_type: Literal["flow_from", "flow_to", None]
stat_energy_key: Literal["stat_energy_from", "stat_energy_to"]
entity_energy_key: Literal["entity_energy_from", "entity_energy_to"]
total_money_key: Literal["stat_cost", "stat_compensation"]
name_suffix: str
entity_id_suffix: str
@ -78,7 +77,6 @@ SOURCE_ADAPTERS: Final = (
"grid",
"flow_from",
"stat_energy_from",
"entity_energy_from",
"stat_cost",
"Cost",
"cost",
@ -87,7 +85,6 @@ SOURCE_ADAPTERS: Final = (
"grid",
"flow_to",
"stat_energy_to",
"entity_energy_to",
"stat_compensation",
"Compensation",
"compensation",
@ -96,7 +93,6 @@ SOURCE_ADAPTERS: Final = (
"gas",
None,
"stat_energy_from",
"entity_energy_from",
"stat_cost",
"Cost",
"cost",
@ -183,13 +179,9 @@ class SensorManager:
# Make sure the right data is there
# If the entity existed, we don't pop it from to_remove so it's removed
if (
config.get(adapter.entity_energy_key) is None
or not valid_entity_id(config[adapter.entity_energy_key])
or (
config.get("entity_energy_price") is None
and config.get("number_energy_price") is None
)
if not valid_entity_id(config[adapter.stat_energy_key]) or (
config.get("entity_energy_price") is None
and config.get("number_energy_price") is None
):
return
@ -224,9 +216,7 @@ class EnergyCostSensor(SensorEntity):
super().__init__()
self._adapter = adapter
self.entity_id = (
f"{config[adapter.entity_energy_key]}_{adapter.entity_id_suffix}"
)
self.entity_id = f"{config[adapter.stat_energy_key]}_{adapter.entity_id_suffix}"
self._attr_device_class = SensorDeviceClass.MONETARY
self._attr_state_class = SensorStateClass.TOTAL
self._config = config
@ -246,7 +236,7 @@ class EnergyCostSensor(SensorEntity):
def _update_cost(self) -> None:
"""Update incurred costs."""
energy_state = self.hass.states.get(
cast(str, self._config[self._adapter.entity_energy_key])
cast(str, self._config[self._adapter.stat_energy_key])
)
if energy_state is None:
@ -344,7 +334,7 @@ class EnergyCostSensor(SensorEntity):
self._reset(energy_state_copy)
elif state_class == SensorStateClass.TOTAL_INCREASING and reset_detected(
self.hass,
cast(str, self._config[self._adapter.entity_energy_key]),
cast(str, self._config[self._adapter.stat_energy_key]),
energy,
float(self._last_energy_sensor_state.state),
self._last_energy_sensor_state,
@ -362,13 +352,11 @@ class EnergyCostSensor(SensorEntity):
async def async_added_to_hass(self) -> None:
"""Register callbacks."""
energy_state = self.hass.states.get(
self._config[self._adapter.entity_energy_key]
)
energy_state = self.hass.states.get(self._config[self._adapter.stat_energy_key])
if energy_state:
name = energy_state.name
else:
name = split_entity_id(self._config[self._adapter.entity_energy_key])[
name = split_entity_id(self._config[self._adapter.stat_energy_key])[
0
].replace("_", " ")
@ -378,7 +366,7 @@ class EnergyCostSensor(SensorEntity):
# Store stat ID in hass.data so frontend can look it up
self.hass.data[DOMAIN]["cost_sensors"][
self._config[self._adapter.entity_energy_key]
self._config[self._adapter.stat_energy_key]
] = self.entity_id
@callback
@ -390,7 +378,7 @@ class EnergyCostSensor(SensorEntity):
self.async_on_remove(
async_track_state_change_event(
self.hass,
cast(str, self._config[self._adapter.entity_energy_key]),
cast(str, self._config[self._adapter.stat_energy_key]),
async_state_changed_listener,
)
)
@ -404,7 +392,7 @@ class EnergyCostSensor(SensorEntity):
async def async_will_remove_from_hass(self) -> None:
"""Handle removing from hass."""
self.hass.data[DOMAIN]["cost_sensors"].pop(
self._config[self._adapter.entity_energy_key]
self._config[self._adapter.stat_energy_key]
)
await super().async_will_remove_from_hass()
@ -423,10 +411,10 @@ class EnergyCostSensor(SensorEntity):
"""Return the unique ID of the sensor."""
entity_registry = er.async_get(self.hass)
if registry_entry := entity_registry.async_get(
self._config[self._adapter.entity_energy_key]
self._config[self._adapter.stat_energy_key]
):
prefix = registry_entry.id
else:
prefix = self._config[self._adapter.entity_energy_key]
prefix = self._config[self._adapter.stat_energy_key]
return f"{prefix}_{self._adapter.source_type}_{self._adapter.entity_id_suffix}"

View File

@ -322,7 +322,7 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
)
)
if flow.get("entity_energy_from") is not None and (
if (
flow.get("entity_energy_price") is not None
or flow.get("number_energy_price") is not None
):
@ -330,7 +330,7 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
functools.partial(
_async_validate_auto_generated_cost_entity,
hass,
flow["entity_energy_from"],
flow["stat_energy_from"],
source_result,
)
)
@ -373,7 +373,7 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
)
)
if flow.get("entity_energy_to") is not None and (
if (
flow.get("entity_energy_price") is not None
or flow.get("number_energy_price") is not None
):
@ -381,7 +381,7 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
functools.partial(
_async_validate_auto_generated_cost_entity,
hass,
flow["entity_energy_to"],
flow["stat_energy_to"],
source_result,
)
)
@ -424,7 +424,7 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
)
)
if source.get("entity_energy_from") is not None and (
if (
source.get("entity_energy_price") is not None
or source.get("number_energy_price") is not None
):
@ -432,7 +432,7 @@ async def async_validate(hass: HomeAssistant) -> EnergyPreferencesValidation:
functools.partial(
_async_validate_auto_generated_cost_entity,
hass,
source["entity_energy_from"],
source["stat_energy_from"],
source_result,
)
)

View File

@ -58,7 +58,6 @@ async def test_cost_sensor_no_states(hass, hass_storage, setup_integration) -> N
"flow_from": [
{
"stat_energy_from": "foo",
"entity_energy_from": "foo",
"stat_cost": None,
"entity_energy_price": "bar",
"number_energy_price": None,
@ -85,7 +84,6 @@ async def test_cost_sensor_attributes(hass, hass_storage, setup_integration) ->
"flow_from": [
{
"stat_energy_from": "sensor.energy_consumption",
"entity_energy_from": "sensor.energy_consumption",
"stat_cost": None,
"entity_energy_price": None,
"number_energy_price": 1,
@ -155,7 +153,6 @@ async def test_cost_sensor_price_entity_total_increasing(
"flow_from": [
{
"stat_energy_from": "sensor.energy_consumption",
"entity_energy_from": "sensor.energy_consumption",
"stat_cost": None,
"entity_energy_price": price_entity,
"number_energy_price": fixed_price,
@ -166,7 +163,6 @@ async def test_cost_sensor_price_entity_total_increasing(
"flow_to": [
{
"stat_energy_to": "sensor.energy_production",
"entity_energy_to": "sensor.energy_production",
"stat_compensation": None,
"entity_energy_price": price_entity,
"number_energy_price": fixed_price,
@ -361,7 +357,6 @@ async def test_cost_sensor_price_entity_total(
"flow_from": [
{
"stat_energy_from": "sensor.energy_consumption",
"entity_energy_from": "sensor.energy_consumption",
"stat_cost": None,
"entity_energy_price": price_entity,
"number_energy_price": fixed_price,
@ -372,7 +367,6 @@ async def test_cost_sensor_price_entity_total(
"flow_to": [
{
"stat_energy_to": "sensor.energy_production",
"entity_energy_to": "sensor.energy_production",
"stat_compensation": None,
"entity_energy_price": price_entity,
"number_energy_price": fixed_price,
@ -569,7 +563,6 @@ async def test_cost_sensor_price_entity_total_no_reset(
"flow_from": [
{
"stat_energy_from": "sensor.energy_consumption",
"entity_energy_from": "sensor.energy_consumption",
"stat_cost": None,
"entity_energy_price": price_entity,
"number_energy_price": fixed_price,
@ -580,7 +573,6 @@ async def test_cost_sensor_price_entity_total_no_reset(
"flow_to": [
{
"stat_energy_to": "sensor.energy_production",
"entity_energy_to": "sensor.energy_production",
"stat_compensation": None,
"entity_energy_price": price_entity,
"number_energy_price": fixed_price,
@ -728,7 +720,6 @@ async def test_cost_sensor_handle_energy_units(
"flow_from": [
{
"stat_energy_from": "sensor.energy_consumption",
"entity_energy_from": "sensor.energy_consumption",
"stat_cost": None,
"entity_energy_price": None,
"number_energy_price": 0.5,
@ -798,7 +789,6 @@ async def test_cost_sensor_handle_price_units(
"flow_from": [
{
"stat_energy_from": "sensor.energy_consumption",
"entity_energy_from": "sensor.energy_consumption",
"stat_cost": None,
"entity_energy_price": "sensor.energy_price",
"number_energy_price": None,
@ -856,7 +846,6 @@ async def test_cost_sensor_handle_gas(
{
"type": "gas",
"stat_energy_from": "sensor.gas_consumption",
"entity_energy_from": "sensor.gas_consumption",
"stat_cost": None,
"entity_energy_price": None,
"number_energy_price": 0.5,
@ -907,7 +896,6 @@ async def test_cost_sensor_handle_gas_kwh(
{
"type": "gas",
"stat_energy_from": "sensor.gas_consumption",
"entity_energy_from": "sensor.gas_consumption",
"stat_cost": None,
"entity_energy_price": None,
"number_energy_price": 0.5,
@ -961,7 +949,6 @@ async def test_cost_sensor_wrong_state_class(
"flow_from": [
{
"stat_energy_from": "sensor.energy_consumption",
"entity_energy_from": "sensor.energy_consumption",
"stat_cost": None,
"entity_energy_price": None,
"number_energy_price": 0.5,
@ -1023,7 +1010,6 @@ async def test_cost_sensor_state_class_measurement_no_reset(
"flow_from": [
{
"stat_energy_from": "sensor.energy_consumption",
"entity_energy_from": "sensor.energy_consumption",
"stat_cost": None,
"entity_energy_price": None,
"number_energy_price": 0.5,
@ -1072,7 +1058,6 @@ async def test_inherit_source_unique_id(hass, hass_storage, setup_integration):
{
"type": "gas",
"stat_energy_from": "sensor.gas_consumption",
"entity_energy_from": "sensor.gas_consumption",
"stat_cost": None,
"entity_energy_price": None,
"number_energy_price": 0.5,

View File

@ -580,7 +580,6 @@ async def test_validation_grid_price_not_exist(
"flow_from": [
{
"stat_energy_from": "sensor.grid_consumption_1",
"entity_energy_from": "sensor.grid_consumption_1",
"entity_energy_price": "sensor.grid_price_1",
"number_energy_price": None,
}
@ -588,7 +587,6 @@ async def test_validation_grid_price_not_exist(
"flow_to": [
{
"stat_energy_to": "sensor.grid_production_1",
"entity_energy_to": "sensor.grid_production_1",
"entity_energy_price": None,
"number_energy_price": 0.10,
}
@ -657,7 +655,6 @@ async def test_validation_grid_auto_cost_entity_errors(
"flow_from": [
{
"stat_energy_from": "sensor.grid_consumption_1",
"entity_energy_from": None,
"entity_energy_price": None,
"number_energy_price": 0.20,
}
@ -665,7 +662,6 @@ async def test_validation_grid_auto_cost_entity_errors(
"flow_to": [
{
"stat_energy_to": "sensor.grid_production_1",
"entity_energy_to": "invalid",
"entity_energy_price": None,
"number_energy_price": 0.10,
}
@ -731,7 +727,6 @@ async def test_validation_grid_price_errors(
"flow_from": [
{
"stat_energy_from": "sensor.grid_consumption_1",
"entity_energy_from": "sensor.grid_consumption_1",
"entity_energy_price": "sensor.grid_price_1",
"number_energy_price": None,
}
@ -778,13 +773,11 @@ async def test_validation_gas(
{
"type": "gas",
"stat_energy_from": "sensor.gas_consumption_4",
"entity_energy_from": "sensor.gas_consumption_4",
"entity_energy_price": "sensor.gas_price_1",
},
{
"type": "gas",
"stat_energy_from": "sensor.gas_consumption_3",
"entity_energy_from": "sensor.gas_consumption_3",
"entity_energy_price": "sensor.gas_price_2",
},
]
@ -890,7 +883,6 @@ async def test_validation_gas_no_costs_tracking(
"type": "gas",
"stat_energy_from": "sensor.gas_consumption_1",
"stat_cost": None,
"entity_energy_from": None,
"entity_energy_price": None,
"number_energy_price": None,
},
@ -926,7 +918,6 @@ async def test_validation_grid_no_costs_tracking(
{
"stat_energy_from": "sensor.grid_energy",
"stat_cost": None,
"entity_energy_from": "sensor.grid_energy",
"entity_energy_price": None,
"number_energy_price": None,
},
@ -935,7 +926,6 @@ async def test_validation_grid_no_costs_tracking(
{
"stat_energy_to": "sensor.grid_energy",
"stat_cost": None,
"entity_energy_to": "sensor.grid_energy",
"entity_energy_price": None,
"number_energy_price": None,
},

View File

@ -97,14 +97,12 @@ async def test_save_preferences(
{
"stat_energy_from": "sensor.heat_pump_meter",
"stat_cost": "heat_pump_kwh_cost",
"entity_energy_from": None,
"entity_energy_price": None,
"number_energy_price": None,
},
{
"stat_energy_from": "sensor.heat_pump_meter_2",
"stat_cost": None,
"entity_energy_from": "sensor.heat_pump_meter_2",
"entity_energy_price": None,
"number_energy_price": 0.20,
},
@ -113,14 +111,12 @@ async def test_save_preferences(
{
"stat_energy_to": "sensor.return_to_grid_peak",
"stat_compensation": None,
"entity_energy_to": None,
"entity_energy_price": None,
"number_energy_price": None,
},
{
"stat_energy_to": "sensor.return_to_grid_offpeak",
"stat_compensation": None,
"entity_energy_to": "sensor.return_to_grid_offpeak",
"entity_energy_price": None,
"number_energy_price": 0.20,
},
@ -181,7 +177,6 @@ async def test_save_preferences(
{
"stat_energy_from": "sensor.heat_pump_meter",
"stat_cost": None,
"entity_energy_from": None,
"entity_energy_price": None,
"number_energy_price": None,
}
@ -221,14 +216,12 @@ async def test_handle_duplicate_from_stat(hass, hass_ws_client) -> None:
{
"stat_energy_from": "sensor.heat_pump_meter",
"stat_cost": None,
"entity_energy_from": None,
"entity_energy_price": None,
"number_energy_price": None,
},
{
"stat_energy_from": "sensor.heat_pump_meter",
"stat_cost": None,
"entity_energy_from": None,
"entity_energy_price": None,
"number_energy_price": None,
},