Fix device class for DSMR gas sensors providing energy readings (#85202)

pull/85247/head
Franck Nijhof 2023-01-05 20:28:13 +01:00 committed by GitHub
parent 26a964b90a
commit 4a48f0d659
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 0 deletions

View File

@ -28,6 +28,7 @@ from homeassistant.const import (
CONF_HOST, CONF_HOST,
CONF_PORT, CONF_PORT,
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
UnitOfEnergy,
UnitOfVolume, UnitOfVolume,
) )
from homeassistant.core import CoreState, Event, HomeAssistant, callback from homeassistant.core import CoreState, Event, HomeAssistant, callback
@ -591,6 +592,21 @@ class DSMREntity(SensorEntity):
"""Entity is only available if there is a telegram.""" """Entity is only available if there is a telegram."""
return self.telegram is not None return self.telegram is not None
@property
def device_class(self) -> SensorDeviceClass | None:
"""Return the device class of this entity."""
device_class = super().device_class
# Override device class for gas sensors providing energy units, like
# kWh, MWh, GJ, etc. In those cases, the class should be energy, not gas
with suppress(ValueError):
if device_class == SensorDeviceClass.GAS and UnitOfEnergy(
str(self.native_unit_of_measurement)
):
return SensorDeviceClass.ENERGY
return device_class
@property @property
def native_value(self) -> StateType: def native_value(self) -> StateType:
"""Return the state of sensor, if available, translate if needed.""" """Return the state of sensor, if available, translate if needed."""

View File

@ -26,6 +26,7 @@ from homeassistant.const import (
STATE_UNAVAILABLE, STATE_UNAVAILABLE,
STATE_UNKNOWN, STATE_UNKNOWN,
VOLUME_CUBIC_METERS, VOLUME_CUBIC_METERS,
UnitOfEnergy,
UnitOfPower, UnitOfPower,
) )
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
@ -804,3 +805,57 @@ async def test_reconnect(hass, dsmr_connection_fixture):
await hass.config_entries.async_unload(mock_entry.entry_id) await hass.config_entries.async_unload(mock_entry.entry_id)
assert mock_entry.state == config_entries.ConfigEntryState.NOT_LOADED assert mock_entry.state == config_entries.ConfigEntryState.NOT_LOADED
async def test_gas_meter_providing_energy_reading(hass, dsmr_connection_fixture):
"""Test that gas providing energy readings use the correct device class."""
(connection_factory, transport, protocol) = dsmr_connection_fixture
from dsmr_parser.obis_references import GAS_METER_READING
from dsmr_parser.objects import MBusObject
entry_data = {
"port": "/dev/ttyUSB0",
"dsmr_version": "2.2",
"precision": 4,
"reconnect_interval": 30,
"serial_id": "1234",
"serial_id_gas": "5678",
}
entry_options = {
"time_between_update": 0,
}
telegram = {
GAS_METER_READING: MBusObject(
[
{"value": datetime.datetime.fromtimestamp(1551642213)},
{"value": Decimal(123.456), "unit": UnitOfEnergy.GIGA_JOULE},
]
),
}
mock_entry = MockConfigEntry(
domain="dsmr", unique_id="/dev/ttyUSB0", data=entry_data, options=entry_options
)
mock_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_entry.entry_id)
await hass.async_block_till_done()
telegram_callback = connection_factory.call_args_list[0][0][2]
telegram_callback(telegram)
await asyncio.sleep(0)
gas_consumption = hass.states.get("sensor.gas_meter_gas_consumption")
assert gas_consumption.state == "123.456"
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.ENERGY
assert (
gas_consumption.attributes.get(ATTR_STATE_CLASS)
== SensorStateClass.TOTAL_INCREASING
)
assert (
gas_consumption.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== UnitOfEnergy.GIGA_JOULE
)