From b3f7f379df235bcd7ebdd2b039932c98e2dff937 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Tue, 30 Jul 2024 16:51:02 +0200 Subject: [PATCH] Upgrade dsmr-parser to 1.4.2 (#121929) --- homeassistant/components/dsmr/manifest.json | 2 +- homeassistant/components/dsmr/sensor.py | 141 ++++++++------ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- tests/components/dsmr/test_mbus_migration.py | 30 +-- tests/components/dsmr/test_sensor.py | 183 ++++++++++--------- 6 files changed, 195 insertions(+), 165 deletions(-) diff --git a/homeassistant/components/dsmr/manifest.json b/homeassistant/components/dsmr/manifest.json index c8f0a78f4dc..5490b2a6503 100644 --- a/homeassistant/components/dsmr/manifest.json +++ b/homeassistant/components/dsmr/manifest.json @@ -7,5 +7,5 @@ "integration_type": "hub", "iot_class": "local_push", "loggers": ["dsmr_parser"], - "requirements": ["dsmr-parser==1.3.1"] + "requirements": ["dsmr-parser==1.4.2"] } diff --git a/homeassistant/components/dsmr/sensor.py b/homeassistant/components/dsmr/sensor.py index ae7b08b7f62..f794d1d05e9 100644 --- a/homeassistant/components/dsmr/sensor.py +++ b/homeassistant/components/dsmr/sensor.py @@ -4,10 +4,11 @@ from __future__ import annotations import asyncio from asyncio import CancelledError -from collections.abc import Callable +from collections.abc import Callable, Generator from contextlib import suppress from dataclasses import dataclass from datetime import timedelta +from enum import IntEnum from functools import partial from dsmr_parser.clients.protocol import create_dsmr_reader, create_tcp_dsmr_reader @@ -15,7 +16,7 @@ from dsmr_parser.clients.rfxtrx_protocol import ( create_rfxtrx_dsmr_reader, create_rfxtrx_tcp_dsmr_reader, ) -from dsmr_parser.objects import DSMRObject, Telegram +from dsmr_parser.objects import DSMRObject, MbusDevice, Telegram import serial from homeassistant.components.sensor import ( @@ -77,6 +78,13 @@ class DSMRSensorEntityDescription(SensorEntityDescription): obis_reference: str +class MbusDeviceType(IntEnum): + """Types of mbus devices (13757-3:2013).""" + + GAS = 3 + WATER = 7 + + SENSORS: tuple[DSMRSensorEntityDescription, ...] = ( DSMRSensorEntityDescription( key="timestamp", @@ -318,7 +326,7 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = ( DSMRSensorEntityDescription( key="belgium_max_current_per_phase", translation_key="max_current_per_phase", - obis_reference="BELGIUM_MAX_CURRENT_PER_PHASE", + obis_reference="FUSE_THRESHOLD_L1", dsmr_versions={"5B"}, device_class=SensorDeviceClass.CURRENT, entity_registry_enabled_default=False, @@ -377,38 +385,36 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = ( ), ) - -def create_mbus_entity( - mbus: int, mtype: int, telegram: Telegram -) -> DSMRSensorEntityDescription | None: - """Create a new MBUS Entity.""" - if mtype == 3 and hasattr(telegram, f"BELGIUM_MBUS{mbus}_METER_READING2"): - return DSMRSensorEntityDescription( - key=f"mbus{mbus}_gas_reading", +SENSORS_MBUS_DEVICE_TYPE: dict[int, tuple[DSMRSensorEntityDescription, ...]] = { + MbusDeviceType.GAS: ( + DSMRSensorEntityDescription( + key="gas_reading", translation_key="gas_meter_reading", - obis_reference=f"BELGIUM_MBUS{mbus}_METER_READING2", + obis_reference="MBUS_METER_READING", is_gas=True, device_class=SensorDeviceClass.GAS, state_class=SensorStateClass.TOTAL_INCREASING, - ) - if mtype == 7 and (hasattr(telegram, f"BELGIUM_MBUS{mbus}_METER_READING1")): - return DSMRSensorEntityDescription( - key=f"mbus{mbus}_water_reading", + ), + ), + MbusDeviceType.WATER: ( + DSMRSensorEntityDescription( + key="water_reading", translation_key="water_meter_reading", - obis_reference=f"BELGIUM_MBUS{mbus}_METER_READING1", + obis_reference="MBUS_METER_READING", is_water=True, device_class=SensorDeviceClass.WATER, state_class=SensorStateClass.TOTAL_INCREASING, - ) - return None + ), + ), +} def device_class_and_uom( - telegram: dict[str, DSMRObject], + data: Telegram | MbusDevice, entity_description: DSMRSensorEntityDescription, ) -> tuple[SensorDeviceClass | None, str | None]: """Get native unit of measurement from telegram,.""" - dsmr_object = getattr(telegram, entity_description.obis_reference) + dsmr_object = getattr(data, entity_description.obis_reference) uom: str | None = getattr(dsmr_object, "unit") or None with suppress(ValueError): if entity_description.device_class == SensorDeviceClass.GAS and ( @@ -460,37 +466,60 @@ def rename_old_gas_to_mbus( dev_reg.async_remove_device(device_id) +def is_supported_description( + data: Telegram | MbusDevice, + description: DSMRSensorEntityDescription, + dsmr_version: str, +) -> bool: + """Check if this is a supported description for this telegram.""" + return hasattr(data, description.obis_reference) and ( + description.dsmr_versions is None or dsmr_version in description.dsmr_versions + ) + + def create_mbus_entities( - hass: HomeAssistant, telegram: Telegram, entry: ConfigEntry -) -> list[DSMREntity]: + hass: HomeAssistant, telegram: Telegram, entry: ConfigEntry, dsmr_version: str +) -> Generator[DSMREntity]: """Create MBUS Entities.""" - entities = [] - for idx in range(1, 5): - if ( - device_type := getattr(telegram, f"BELGIUM_MBUS{idx}_DEVICE_TYPE", None) - ) is None: + mbus_devices: list[MbusDevice] = getattr(telegram, "MBUS_DEVICES", []) + for device in mbus_devices: + if (device_type := getattr(device, "MBUS_DEVICE_TYPE", None)) is None: continue - if (type_ := int(device_type.value)) not in (3, 7): - continue - if identifier := getattr( - telegram, f"BELGIUM_MBUS{idx}_EQUIPMENT_IDENTIFIER", None - ): + type_ = int(device_type.value) + + if identifier := getattr(device, "MBUS_EQUIPMENT_IDENTIFIER", None): serial_ = identifier.value rename_old_gas_to_mbus(hass, entry, serial_) else: serial_ = "" - if description := create_mbus_entity(idx, type_, telegram): - entities.append( - DSMREntity( - description, - entry, - telegram, - *device_class_and_uom(telegram, description), # type: ignore[arg-type] - serial_, - idx, - ) + + for description in SENSORS_MBUS_DEVICE_TYPE.get(type_, ()): + if not is_supported_description(device, description, dsmr_version): + continue + yield DSMREntity( + description, + entry, + telegram, + *device_class_and_uom(device, description), # type: ignore[arg-type] + serial_, + device.channel_id, ) - return entities + + +def get_dsmr_object( + telegram: Telegram | None, mbus_id: int, obis_reference: str +) -> DSMRObject | None: + """Extract DSMR object from telegram.""" + if not telegram: + return None + + telegram_or_device: Telegram | MbusDevice | None = telegram + if mbus_id: + telegram_or_device = telegram.get_mbus_device_by_channel(mbus_id) + if telegram_or_device is None: + return None + + return getattr(telegram_or_device, obis_reference, None) async def async_setup_entry( @@ -510,8 +539,7 @@ async def async_setup_entry( add_entities_handler() add_entities_handler = None - if dsmr_version == "5B": - entities.extend(create_mbus_entities(hass, telegram, entry)) + entities.extend(create_mbus_entities(hass, telegram, entry, dsmr_version)) entities.extend( [ @@ -522,12 +550,8 @@ async def async_setup_entry( *device_class_and_uom(telegram, description), # type: ignore[arg-type] ) for description in SENSORS - if ( - description.dsmr_versions is None - or dsmr_version in description.dsmr_versions - ) + if is_supported_description(telegram, description, dsmr_version) and (not description.is_gas or CONF_SERIAL_ID_GAS in entry.data) - and hasattr(telegram, description.obis_reference) ] ) async_add_entities(entities) @@ -723,6 +747,7 @@ class DSMREntity(SensorEntity): identifiers={(DOMAIN, device_serial)}, name=device_name, ) + self._mbus_id = mbus_id if mbus_id != 0: if serial_id: self._attr_unique_id = f"{device_serial}" @@ -737,20 +762,22 @@ class DSMREntity(SensorEntity): self.telegram = telegram if self.hass and ( telegram is None - or hasattr(telegram, self.entity_description.obis_reference) + or get_dsmr_object( + telegram, self._mbus_id, self.entity_description.obis_reference + ) ): self.async_write_ha_state() def get_dsmr_object_attr(self, attribute: str) -> str | None: """Read attribute from last received telegram for this DSMR object.""" - # Make sure telegram contains an object for this entities obis - if self.telegram is None or not hasattr( - self.telegram, self.entity_description.obis_reference - ): + # Get the object + dsmr_object = get_dsmr_object( + self.telegram, self._mbus_id, self.entity_description.obis_reference + ) + if dsmr_object is None: return None # Get the attribute value if the object has it - dsmr_object = getattr(self.telegram, self.entity_description.obis_reference) attr: str | None = getattr(dsmr_object, attribute) return attr diff --git a/requirements_all.txt b/requirements_all.txt index 7a63bcb5602..4d74e059a59 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -750,7 +750,7 @@ dremel3dpy==2.1.1 dropmqttapi==1.0.3 # homeassistant.components.dsmr -dsmr-parser==1.3.1 +dsmr-parser==1.4.2 # homeassistant.components.dwd_weather_warnings dwdwfsapi==1.0.7 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 9e8664f4821..86fdf2da7f9 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -640,7 +640,7 @@ dremel3dpy==2.1.1 dropmqttapi==1.0.3 # homeassistant.components.dsmr -dsmr-parser==1.3.1 +dsmr-parser==1.4.2 # homeassistant.components.dwd_weather_warnings dwdwfsapi==1.0.7 diff --git a/tests/components/dsmr/test_mbus_migration.py b/tests/components/dsmr/test_mbus_migration.py index cd3db27be8c..a28bc2c3a33 100644 --- a/tests/components/dsmr/test_mbus_migration.py +++ b/tests/components/dsmr/test_mbus_migration.py @@ -5,9 +5,9 @@ from decimal import Decimal from unittest.mock import MagicMock from dsmr_parser.obis_references import ( - BELGIUM_MBUS1_DEVICE_TYPE, - BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER, - BELGIUM_MBUS1_METER_READING2, + MBUS_DEVICE_TYPE, + MBUS_EQUIPMENT_IDENTIFIER, + MBUS_METER_READING, ) from dsmr_parser.objects import CosemObject, MBusObject, Telegram @@ -67,20 +67,20 @@ async def test_migrate_gas_to_mbus( telegram = Telegram() telegram.add( - BELGIUM_MBUS1_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 1), [{"value": "003", "unit": ""}]), - "BELGIUM_MBUS1_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 1), [{"value": "37464C4F32313139303333373331", "unit": ""}], ), - "BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS1_METER_READING2, + MBUS_METER_READING, MBusObject( (0, 1), [ @@ -88,7 +88,7 @@ async def test_migrate_gas_to_mbus( {"value": Decimal(745.695), "unit": "m3"}, ], ), - "BELGIUM_MBUS1_METER_READING2", + "MBUS_METER_READING", ) assert await hass.config_entries.async_setup(mock_entry.entry_id) @@ -184,20 +184,20 @@ async def test_migrate_gas_to_mbus_exists( telegram = Telegram() telegram.add( - BELGIUM_MBUS1_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 0), [{"value": "003", "unit": ""}]), - "BELGIUM_MBUS1_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 1), [{"value": "37464C4F32313139303333373331", "unit": ""}], ), - "BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS1_METER_READING2, + MBUS_METER_READING, MBusObject( (0, 1), [ @@ -205,7 +205,7 @@ async def test_migrate_gas_to_mbus_exists( {"value": Decimal(745.695), "unit": "m3"}, ], ), - "BELGIUM_MBUS1_METER_READING2", + "MBUS_METER_READING", ) assert await hass.config_entries.async_setup(mock_entry.entry_id) diff --git a/tests/components/dsmr/test_sensor.py b/tests/components/dsmr/test_sensor.py index 5b0cf6d7a15..b93dd8d18d2 100644 --- a/tests/components/dsmr/test_sensor.py +++ b/tests/components/dsmr/test_sensor.py @@ -15,33 +15,20 @@ from dsmr_parser import obis_references from dsmr_parser.obis_references import ( BELGIUM_CURRENT_AVERAGE_DEMAND, BELGIUM_MAXIMUM_DEMAND_MONTH, - BELGIUM_MBUS1_DEVICE_TYPE, - BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER, - BELGIUM_MBUS1_METER_READING1, - BELGIUM_MBUS1_METER_READING2, - BELGIUM_MBUS2_DEVICE_TYPE, - BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER, - BELGIUM_MBUS2_METER_READING1, - BELGIUM_MBUS2_METER_READING2, - BELGIUM_MBUS3_DEVICE_TYPE, - BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER, - BELGIUM_MBUS3_METER_READING1, - BELGIUM_MBUS3_METER_READING2, - BELGIUM_MBUS4_DEVICE_TYPE, - BELGIUM_MBUS4_EQUIPMENT_IDENTIFIER, - BELGIUM_MBUS4_METER_READING1, - BELGIUM_MBUS4_METER_READING2, CURRENT_ELECTRICITY_USAGE, ELECTRICITY_ACTIVE_TARIFF, ELECTRICITY_EXPORTED_TOTAL, ELECTRICITY_IMPORTED_TOTAL, GAS_METER_READING, HOURLY_GAS_METER_READING, + MBUS_DEVICE_TYPE, + MBUS_EQUIPMENT_IDENTIFIER, + MBUS_METER_READING, ) from dsmr_parser.objects import CosemObject, MBusObject, Telegram import pytest -from homeassistant.components.dsmr.sensor import SENSORS +from homeassistant.components.dsmr.sensor import SENSORS, SENSORS_MBUS_DEVICE_TYPE from homeassistant.components.sensor import ( ATTR_OPTIONS, ATTR_STATE_CLASS, @@ -562,20 +549,20 @@ async def test_belgian_meter( "BELGIUM_MAXIMUM_DEMAND_MONTH", ) telegram.add( - BELGIUM_MBUS1_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 1), [{"value": "003", "unit": ""}]), - "BELGIUM_MBUS1_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 1), [{"value": "37464C4F32313139303333373331", "unit": ""}], ), - "BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS1_METER_READING2, + MBUS_METER_READING, MBusObject( (0, 1), [ @@ -583,23 +570,23 @@ async def test_belgian_meter( {"value": Decimal(745.695), "unit": "m3"}, ], ), - "BELGIUM_MBUS1_METER_READING2", + "MBUS_METER_READING", ) telegram.add( - BELGIUM_MBUS2_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 2), [{"value": "007", "unit": ""}]), - "BELGIUM_MBUS2_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 2), [{"value": "37464C4F32313139303333373332", "unit": ""}], ), - "BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS2_METER_READING1, + MBUS_METER_READING, MBusObject( (0, 2), [ @@ -607,23 +594,23 @@ async def test_belgian_meter( {"value": Decimal(678.695), "unit": "m3"}, ], ), - "BELGIUM_MBUS2_METER_READING1", + "MBUS_METER_READING", ) telegram.add( - BELGIUM_MBUS3_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 3), [{"value": "003", "unit": ""}]), - "BELGIUM_MBUS3_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 3), [{"value": "37464C4F32313139303333373333", "unit": ""}], ), - "BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS3_METER_READING2, + MBUS_METER_READING, MBusObject( (0, 3), [ @@ -631,23 +618,23 @@ async def test_belgian_meter( {"value": Decimal(12.12), "unit": "m3"}, ], ), - "BELGIUM_MBUS3_METER_READING2", + "MBUS_METER_READING", ) telegram.add( - BELGIUM_MBUS4_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 4), [{"value": "007", "unit": ""}]), - "BELGIUM_MBUS4_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS4_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 4), [{"value": "37464C4F32313139303333373334", "unit": ""}], ), - "BELGIUM_MBUS4_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS4_METER_READING1, + MBUS_METER_READING, MBusObject( (0, 4), [ @@ -655,7 +642,7 @@ async def test_belgian_meter( {"value": Decimal(13.13), "unit": "m3"}, ], ), - "BELGIUM_MBUS4_METER_READING1", + "MBUS_METER_READING", ) telegram.add( ELECTRICITY_ACTIVE_TARIFF, @@ -777,20 +764,20 @@ async def test_belgian_meter_alt( telegram = Telegram() telegram.add( - BELGIUM_MBUS1_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 1), [{"value": "007", "unit": ""}]), - "BELGIUM_MBUS1_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 1), [{"value": "37464C4F32313139303333373331", "unit": ""}], ), - "BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS1_METER_READING1, + MBUS_METER_READING, MBusObject( (0, 1), [ @@ -798,23 +785,23 @@ async def test_belgian_meter_alt( {"value": Decimal(123.456), "unit": "m3"}, ], ), - "BELGIUM_MBUS1_METER_READING1", + "MBUS_METER_READING", ) telegram.add( - BELGIUM_MBUS2_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 2), [{"value": "003", "unit": ""}]), - "BELGIUM_MBUS2_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 2), [{"value": "37464C4F32313139303333373332", "unit": ""}], ), - "BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS2_METER_READING2, + MBUS_METER_READING, MBusObject( (0, 2), [ @@ -822,23 +809,23 @@ async def test_belgian_meter_alt( {"value": Decimal(678.901), "unit": "m3"}, ], ), - "BELGIUM_MBUS2_METER_READING2", + "MBUS_METER_READING", ) telegram.add( - BELGIUM_MBUS3_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 3), [{"value": "007", "unit": ""}]), - "BELGIUM_MBUS3_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 3), [{"value": "37464C4F32313139303333373333", "unit": ""}], ), - "BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS3_METER_READING1, + MBUS_METER_READING, MBusObject( (0, 3), [ @@ -846,23 +833,23 @@ async def test_belgian_meter_alt( {"value": Decimal(12.12), "unit": "m3"}, ], ), - "BELGIUM_MBUS3_METER_READING1", + "MBUS_METER_READING", ) telegram.add( - BELGIUM_MBUS4_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 4), [{"value": "003", "unit": ""}]), - "BELGIUM_MBUS4_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS4_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 4), [{"value": "37464C4F32313139303333373334", "unit": ""}], ), - "BELGIUM_MBUS4_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS4_METER_READING2, + MBUS_METER_READING, MBusObject( (0, 4), [ @@ -870,7 +857,7 @@ async def test_belgian_meter_alt( {"value": Decimal(13.13), "unit": "m3"}, ], ), - "BELGIUM_MBUS4_METER_READING2", + "MBUS_METER_READING", ) mock_entry = MockConfigEntry( @@ -970,46 +957,46 @@ async def test_belgian_meter_mbus( "ELECTRICITY_ACTIVE_TARIFF", ) telegram.add( - BELGIUM_MBUS1_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 1), [{"value": "006", "unit": ""}]), - "BELGIUM_MBUS1_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 1), [{"value": "37464C4F32313139303333373331", "unit": ""}], ), - "BELGIUM_MBUS1_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS2_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 2), [{"value": "003", "unit": ""}]), - "BELGIUM_MBUS2_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 2), [{"value": "37464C4F32313139303333373332", "unit": ""}], ), - "BELGIUM_MBUS2_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS3_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 3), [{"value": "007", "unit": ""}]), - "BELGIUM_MBUS3_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER, + MBUS_EQUIPMENT_IDENTIFIER, CosemObject( (0, 3), [{"value": "37464C4F32313139303333373333", "unit": ""}], ), - "BELGIUM_MBUS3_EQUIPMENT_IDENTIFIER", + "MBUS_EQUIPMENT_IDENTIFIER", ) telegram.add( - BELGIUM_MBUS3_METER_READING2, + MBUS_METER_READING, MBusObject( (0, 3), [ @@ -1017,15 +1004,15 @@ async def test_belgian_meter_mbus( {"value": Decimal(12.12), "unit": "m3"}, ], ), - "BELGIUM_MBUS3_METER_READING2", + "MBUS_METER_READING", ) telegram.add( - BELGIUM_MBUS4_DEVICE_TYPE, + MBUS_DEVICE_TYPE, CosemObject((0, 4), [{"value": "007", "unit": ""}]), - "BELGIUM_MBUS4_DEVICE_TYPE", + "MBUS_DEVICE_TYPE", ) telegram.add( - BELGIUM_MBUS4_METER_READING1, + MBUS_METER_READING, MBusObject( (0, 4), [ @@ -1033,7 +1020,7 @@ async def test_belgian_meter_mbus( {"value": Decimal(13.13), "unit": "m3"}, ], ), - "BELGIUM_MBUS4_METER_READING1", + "MBUS_METER_READING", ) mock_entry = MockConfigEntry( @@ -1057,20 +1044,32 @@ async def test_belgian_meter_mbus( active_tariff = hass.states.get("sensor.electricity_meter_active_tariff") assert active_tariff.state == "unknown" - # check if gas consumption mbus2 is parsed correctly + # check if gas consumption mbus1 is parsed correctly gas_consumption = hass.states.get("sensor.gas_meter_gas_consumption") assert gas_consumption is None - # check if water usage mbus3 is parsed correctly - water_consumption = hass.states.get("sensor.water_meter_water_consumption_2") - assert water_consumption is None - - # check if gas consumption mbus4 is parsed correctly + # check if gas consumption mbus2 is parsed correctly gas_consumption = hass.states.get("sensor.gas_meter_gas_consumption_2") assert gas_consumption is None - # check if gas consumption mbus4 is parsed correctly + # check if water usage mbus3 is parsed correctly water_consumption = hass.states.get("sensor.water_meter_water_consumption") + assert water_consumption + assert water_consumption.state == "12.12" + assert ( + water_consumption.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.WATER + ) + assert ( + water_consumption.attributes.get(ATTR_STATE_CLASS) + == SensorStateClass.TOTAL_INCREASING + ) + assert ( + water_consumption.attributes.get(ATTR_UNIT_OF_MEASUREMENT) + == UnitOfVolume.CUBIC_METERS + ) + + # check if gas consumption mbus4 is parsed correctly + water_consumption = hass.states.get("sensor.water_meter_water_consumption_2") assert water_consumption.state == "13.13" assert ( water_consumption.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.WATER @@ -1526,3 +1525,7 @@ def test_all_obis_references_exists(): """Verify that all attributes exist by name in database.""" for sensor in SENSORS: assert hasattr(obis_references, sensor.obis_reference) + + for sensors in SENSORS_MBUS_DEVICE_TYPE.values(): + for sensor in sensors: + assert hasattr(obis_references, sensor.obis_reference)