diff --git a/homeassistant/components/energy/sensor.py b/homeassistant/components/energy/sensor.py index 1d919e07737..207003303e2 100644 --- a/homeassistant/components/energy/sensor.py +++ b/homeassistant/components/energy/sensor.py @@ -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 diff --git a/tests/components/energy/test_sensor.py b/tests/components/energy/test_sensor.py index 3d0eb5b1318..133cde814aa 100644 --- a/tests/components/energy/test_sensor.py +++ b/tests/components/energy/test_sensor.py @@ -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