Add kWh as cost option for gas (#58426)

* Add kWh as cost option for GAS

* Add kWh as cost option for GAS (pylint)

* Add kWh as cost option for GAS (make CONST)

* Change GAS_UNITS to VALID_ENERGY_UNITS

* Add test for Gas cost in kWh (2)

* Back off ENERGY_WATT_HOUR - unlikely for gas

* Add MEGA_WATT_HOUR support (2)

* Normalise pricing for MEGA_WATT_HOUR

* Normalise pricing for MEGA_WATT_HOUR
This commit is contained in:
Colin Robbins 2021-10-27 17:06:32 +01:00 committed by GitHub
parent 0111b28a67
commit 39998f5387
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 123 additions and 9 deletions

View File

@ -20,6 +20,7 @@ from homeassistant.components.sensor.recorder import reset_detected
from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT,
ENERGY_KILO_WATT_HOUR,
ENERGY_MEGA_WATT_HOUR,
ENERGY_WATT_HOUR,
VOLUME_CUBIC_METERS,
)
@ -43,6 +44,8 @@ SUPPORTED_STATE_CLASSES = [
STATE_CLASS_TOTAL,
STATE_CLASS_TOTAL_INCREASING,
]
VALID_ENERGY_UNITS = [ENERGY_WATT_HOUR, ENERGY_KILO_WATT_HOUR, ENERGY_MEGA_WATT_HOUR]
VALID_ENERGY_UNITS_GAS = [VOLUME_CUBIC_METERS] + VALID_ENERGY_UNITS
_LOGGER = logging.getLogger(__name__)
@ -289,14 +292,16 @@ class EnergyCostSensor(SensorEntity):
except ValueError:
return
if (
self._adapter.source_type == "grid"
and energy_price_state.attributes.get(
ATTR_UNIT_OF_MEASUREMENT, ""
).endswith(f"/{ENERGY_WATT_HOUR}")
if energy_price_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT, "").endswith(
f"/{ENERGY_WATT_HOUR}"
):
energy_price *= 1000.0
if energy_price_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT, "").endswith(
f"/{ENERGY_MEGA_WATT_HOUR}"
):
energy_price /= 1000.0
else:
energy_price_state = None
energy_price = cast(float, self._config["number_energy_price"])
@ -309,15 +314,18 @@ class EnergyCostSensor(SensorEntity):
energy_unit = energy_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
if self._adapter.source_type == "grid":
if energy_unit == ENERGY_WATT_HOUR:
energy_price /= 1000
elif energy_unit != ENERGY_KILO_WATT_HOUR:
if energy_unit not in VALID_ENERGY_UNITS:
energy_unit = None
elif self._adapter.source_type == "gas":
if energy_unit != VOLUME_CUBIC_METERS:
if energy_unit not in VALID_ENERGY_UNITS_GAS:
energy_unit = None
if energy_unit == ENERGY_WATT_HOUR:
energy_price /= 1000
elif energy_unit == ENERGY_MEGA_WATT_HOUR:
energy_unit *= 1000
if energy_unit is None:
if not self._wrong_unit_reported:
self._wrong_unit_reported = True

View File

@ -19,6 +19,7 @@ from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT,
DEVICE_CLASS_MONETARY,
ENERGY_KILO_WATT_HOUR,
ENERGY_MEGA_WATT_HOUR,
ENERGY_WATT_HOUR,
STATE_UNKNOWN,
VOLUME_CUBIC_METERS,
@ -718,6 +719,62 @@ async def test_cost_sensor_handle_wh(hass, hass_storage) -> None:
assert state.state == "5.0"
async def test_cost_sensor_handle_mwh(hass, hass_storage) -> None:
"""Test energy cost price from sensor entity."""
energy_attributes = {
ATTR_UNIT_OF_MEASUREMENT: ENERGY_MEGA_WATT_HOUR,
ATTR_STATE_CLASS: STATE_CLASS_TOTAL_INCREASING,
}
energy_data = data.EnergyManager.default_preferences()
energy_data["energy_sources"].append(
{
"type": "grid",
"flow_from": [
{
"stat_energy_from": "sensor.energy_consumption",
"entity_energy_from": "sensor.energy_consumption",
"stat_cost": None,
"entity_energy_price": None,
"number_energy_price": 2.0,
}
],
"flow_to": [],
"cost_adjustment_day": 0,
}
)
hass_storage[data.STORAGE_KEY] = {
"version": 1,
"data": energy_data,
}
now = dt_util.utcnow()
# Initial state: 0.5MWh
hass.states.async_set(
"sensor.energy_consumption",
0.5,
energy_attributes,
)
with patch("homeassistant.util.dt.utcnow", return_value=now):
await setup_integration(hass)
state = hass.states.get("sensor.energy_consumption_cost")
assert state.state == "0.0"
# Energy use bumped by 1 MWh
hass.states.async_set(
"sensor.energy_consumption",
1.5,
energy_attributes,
)
await hass.async_block_till_done()
state = hass.states.get("sensor.energy_consumption_cost")
assert state.state == "2.0"
async def test_cost_sensor_handle_gas(hass, hass_storage) -> None:
"""Test gas cost price from sensor entity."""
energy_attributes = {
@ -767,6 +824,55 @@ async def test_cost_sensor_handle_gas(hass, hass_storage) -> None:
assert state.state == "50.0"
async def test_cost_sensor_handle_gas_kwh(hass, hass_storage) -> None:
"""Test gas cost price from sensor entity."""
energy_attributes = {
ATTR_UNIT_OF_MEASUREMENT: ENERGY_KILO_WATT_HOUR,
ATTR_STATE_CLASS: STATE_CLASS_TOTAL_INCREASING,
}
energy_data = data.EnergyManager.default_preferences()
energy_data["energy_sources"].append(
{
"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,
}
)
hass_storage[data.STORAGE_KEY] = {
"version": 1,
"data": energy_data,
}
now = dt_util.utcnow()
hass.states.async_set(
"sensor.gas_consumption",
100,
energy_attributes,
)
with patch("homeassistant.util.dt.utcnow", return_value=now):
await setup_integration(hass)
state = hass.states.get("sensor.gas_consumption_cost")
assert state.state == "0.0"
# gas use bumped to 10 kWh
hass.states.async_set(
"sensor.gas_consumption",
200,
energy_attributes,
)
await hass.async_block_till_done()
state = hass.states.get("sensor.gas_consumption_cost")
assert state.state == "50.0"
@pytest.mark.parametrize("state_class", [None])
async def test_cost_sensor_wrong_state_class(
hass, hass_storage, caplog, state_class