Dsmr eon hungary (#138162)

Add EON hungary
This commit is contained in:
balazs92117 2025-02-11 17:25:57 +01:00 committed by GitHub
parent ab1e1c06b6
commit a85bb98743
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 303 additions and 10 deletions

View File

@ -59,7 +59,7 @@ class DSMRConnection:
self._equipment_identifier = obis_ref.EQUIPMENT_IDENTIFIER
if dsmr_version == "5B":
self._equipment_identifier = obis_ref.BELGIUM_EQUIPMENT_IDENTIFIER
if dsmr_version == "5L":
if dsmr_version in ("5L", "5EONHU"):
self._equipment_identifier = obis_ref.LUXEMBOURG_EQUIPMENT_IDENTIFIER
if dsmr_version == "Q3D":
self._equipment_identifier = obis_ref.Q3D_EQUIPMENT_IDENTIFIER

View File

@ -28,7 +28,7 @@ DEVICE_NAME_GAS = "Gas Meter"
DEVICE_NAME_WATER = "Water Meter"
DEVICE_NAME_HEAT = "Heat Meter"
DSMR_VERSIONS = {"2.2", "4", "5", "5B", "5L", "5S", "Q3D"}
DSMR_VERSIONS = {"2.2", "4", "5", "5B", "5L", "5S", "Q3D", "5EONHU"}
DSMR_PROTOCOL = "dsmr_protocol"
RFXTRX_DSMR_PROTOCOL = "rfxtrx_dsmr_protocol"

View File

@ -115,7 +115,7 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
key="electricity_active_tariff",
translation_key="electricity_active_tariff",
obis_reference="ELECTRICITY_ACTIVE_TARIFF",
dsmr_versions={"2.2", "4", "5", "5B", "5L"},
dsmr_versions={"2.2", "4", "5", "5B", "5L", "5EONHU"},
device_class=SensorDeviceClass.ENUM,
options=["low", "normal"],
),
@ -123,7 +123,7 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
key="electricity_used_tariff_1",
translation_key="electricity_used_tariff_1",
obis_reference="ELECTRICITY_USED_TARIFF_1",
dsmr_versions={"2.2", "4", "5", "5B", "5L"},
dsmr_versions={"2.2", "4", "5", "5B", "5L", "5EONHU"},
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
@ -131,7 +131,25 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
key="electricity_used_tariff_2",
translation_key="electricity_used_tariff_2",
obis_reference="ELECTRICITY_USED_TARIFF_2",
dsmr_versions={"2.2", "4", "5", "5B", "5L"},
dsmr_versions={"2.2", "4", "5", "5B", "5L", "5EONHU"},
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
DSMRSensorEntityDescription(
key="electricity_used_tariff_3",
translation_key="electricity_used_tariff_3",
obis_reference="ELECTRICITY_USED_TARIFF_3",
dsmr_versions={"5EONHU"},
force_update=True,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
DSMRSensorEntityDescription(
key="electricity_used_tariff_4",
translation_key="electricity_used_tariff_4",
obis_reference="ELECTRICITY_USED_TARIFF_4",
dsmr_versions={"5EONHU"},
force_update=True,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
@ -139,7 +157,7 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
key="electricity_delivered_tariff_1",
translation_key="electricity_delivered_tariff_1",
obis_reference="ELECTRICITY_DELIVERED_TARIFF_1",
dsmr_versions={"2.2", "4", "5", "5B", "5L"},
dsmr_versions={"2.2", "4", "5", "5B", "5L", "5EONHU"},
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
@ -147,7 +165,25 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
key="electricity_delivered_tariff_2",
translation_key="electricity_delivered_tariff_2",
obis_reference="ELECTRICITY_DELIVERED_TARIFF_2",
dsmr_versions={"2.2", "4", "5", "5B", "5L"},
dsmr_versions={"2.2", "4", "5", "5B", "5L", "5EONHU"},
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
DSMRSensorEntityDescription(
key="electricity_delivered_tariff_3",
translation_key="electricity_delivered_tariff_3",
obis_reference="ELECTRICITY_DELIVERED_TARIFF_3",
dsmr_versions={"5EONHU"},
force_update=True,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
DSMRSensorEntityDescription(
key="electricity_delivered_tariff_4",
translation_key="electricity_delivered_tariff_4",
obis_reference="ELECTRICITY_DELIVERED_TARIFF_4",
dsmr_versions={"5EONHU"},
force_update=True,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
@ -341,7 +377,7 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
key="electricity_imported_total",
translation_key="electricity_imported_total",
obis_reference="ELECTRICITY_IMPORTED_TOTAL",
dsmr_versions={"5L", "5S", "Q3D"},
dsmr_versions={"5L", "5S", "Q3D", "5EONHU"},
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
@ -349,7 +385,7 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
key="electricity_exported_total",
translation_key="electricity_exported_total",
obis_reference="ELECTRICITY_EXPORTED_TOTAL",
dsmr_versions={"5L", "5S", "Q3D"},
dsmr_versions={"5L", "5S", "Q3D", "5EONHU"},
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
),
@ -387,6 +423,113 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.GAS,
state_class=SensorStateClass.TOTAL_INCREASING,
),
DSMRSensorEntityDescription(
key="actual_threshold_electricity",
translation_key="actual_threshold_electricity",
obis_reference="ACTUAL_TRESHOLD_ELECTRICITY", # Misspelled in external tool
dsmr_versions={"5EONHU"},
device_class=SensorDeviceClass.POWER,
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
key="eon_hu_electricity_combined",
translation_key="electricity_combined",
obis_reference="EON_HU_ELECTRICITY_COMBINED",
dsmr_versions={"5EONHU"},
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL,
),
DSMRSensorEntityDescription(
key="eon_hu_instantaneous_power_factor_total",
translation_key="instantaneous_power_factor_total",
obis_reference="EON_HU_INSTANTANEOUS_POWER_FACTOR_TOTAL",
dsmr_versions={"5EONHU"},
entity_registry_enabled_default=False,
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
key="eon_hu_instantaneous_power_factor_l1",
translation_key="instantaneous_power_factor_l1",
obis_reference="EON_HU_INSTANTANEOUS_POWER_FACTOR_L1",
dsmr_versions={"5EONHU"},
entity_registry_enabled_default=False,
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
key="eon_hu_instantaneous_power_factor_l2",
translation_key="instantaneous_power_factor_l2",
obis_reference="EON_HU_INSTANTANEOUS_POWER_FACTOR_L2",
dsmr_versions={"5EONHU"},
entity_registry_enabled_default=False,
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
key="eon_hu_instantaneous_power_factor_l3",
translation_key="instantaneous_power_factor_l3",
obis_reference="EON_HU_INSTANTANEOUS_POWER_FACTOR_L3",
dsmr_versions={"5EONHU"},
entity_registry_enabled_default=False,
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
key="eon_hu_frequency",
translation_key="frequency",
obis_reference="EON_HU_FREQUENCY",
dsmr_versions={"5EONHU"},
entity_registry_enabled_default=False,
device_class=SensorDeviceClass.FREQUENCY,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
key="fuse_threshold_l1",
translation_key="fuse_threshold_l1",
obis_reference="FUSE_THRESHOLD_L1",
dsmr_versions={"5EONHU"},
device_class=SensorDeviceClass.CURRENT,
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
key="fuse_threshold_l2",
translation_key="fuse_threshold_l2",
obis_reference="FUSE_THRESHOLD_L2",
dsmr_versions={"5EONHU"},
device_class=SensorDeviceClass.CURRENT,
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
key="fuse_threshold_l3",
translation_key="fuse_threshold_l3",
obis_reference="FUSE_THRESHOLD_L3",
dsmr_versions={"5EONHU"},
device_class=SensorDeviceClass.CURRENT,
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
DSMRSensorEntityDescription(
key="text_message",
translation_key="text_message",
obis_reference="TEXT_MESSAGE",
dsmr_versions={"5EONHU"},
entity_registry_enabled_default=False,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
)
SENSORS_MBUS_DEVICE_TYPE: dict[int, tuple[DSMRSensorEntityDescription, ...]] = {
@ -844,8 +987,9 @@ class DSMREntity(SensorEntity):
def translate_tariff(value: str, dsmr_version: str) -> str | None:
"""Convert 2/1 to normal/low depending on DSMR version."""
# DSMR V5B: Note: In Belgium values are swapped:
# DSMR V5EONHU: Note: In EON HUngary values are swapped:
# Rate code 2 is used for low rate and rate code 1 is used for normal rate.
if dsmr_version == "5B":
if dsmr_version in ("5B", "5EONHU"):
if value == "0001":
value = "0002"
elif value == "0002":

View File

@ -61,6 +61,12 @@
"electricity_delivered_tariff_2": {
"name": "Energy production (tarif 2)"
},
"electricity_delivered_tariff_3": {
"name": "Energy production (tarif 3)"
},
"electricity_delivered_tariff_4": {
"name": "Energy production (tarif 4)"
},
"electricity_exported_total": {
"name": "Energy production (total)"
},
@ -73,6 +79,12 @@
"electricity_used_tariff_2": {
"name": "Energy consumption (tarif 2)"
},
"electricity_used_tariff_3": {
"name": "Energy consumption (tarif 3)"
},
"electricity_used_tariff_4": {
"name": "Energy consumption (tarif 4)"
},
"gas_meter_reading": {
"name": "Gas consumption"
},
@ -150,6 +162,57 @@
},
"water_meter_reading": {
"name": "Water consumption"
},
"actual_threshold_electricity": {
"name": "Actual threshold electricity"
},
"electricity_reactive_imported_total": {
"name": "Imported reactive electricity (total)"
},
"electricity_reactive_exported_total": {
"name": "Exported reactive electricity (total)"
},
"electricity_reactive_total_q1": {
"name": "Reactive electricity (Q1)"
},
"electricity_reactive_total_q2": {
"name": "Reactive electricity (Q2)"
},
"electricity_reactive_total_q3": {
"name": "Reactive electricity (Q3)"
},
"electricity_reactive_total_q4": {
"name": "Reactive electricity (Q4)"
},
"electricity_combined": {
"name": "Energy combined"
},
"instantaneous_power_factor_total": {
"name": "Instantaneous power factor (total)"
},
"instantaneous_power_factor_l1": {
"name": "Instantaneous power factor L1"
},
"instantaneous_power_factor_l2": {
"name": "Instantaneous power factor L2"
},
"instantaneous_power_factor_l3": {
"name": "Instantaneous power factor L3"
},
"frequency": {
"name": "Frequency"
},
"fuse_threshold_l1": {
"name": "Fuse threshold on L1"
},
"fuse_threshold_l2": {
"name": "Fuse threshold on L2"
},
"fuse_threshold_l3": {
"name": "Fuse threshold on L3"
},
"text_message": {
"name": "Text message"
}
}
},

View File

@ -113,6 +113,12 @@ def dsmr_connection_send_validate_fixture() -> Generator[
EQUIPMENT_IDENTIFIER_GAS, [{"value": "123456789", "unit": ""}]
),
}
if args[1] == "5EONHU":
protocol.telegram = {
LUXEMBOURG_EQUIPMENT_IDENTIFIER: CosemObject(
LUXEMBOURG_EQUIPMENT_IDENTIFIER, [{"value": "12345678", "unit": ""}]
),
}
if args[1] == "5S":
protocol.telegram = {
P1_MESSAGE_TIMESTAMP: CosemObject(

View File

@ -163,6 +163,16 @@ async def test_setup_network_rfxtrx(
"serial_id_gas": "123456789",
},
),
(
"5EONHU",
{
"port": "/dev/ttyUSB1234",
"dsmr_version": "5EONHU",
"protocol": "dsmr_protocol",
"serial_id": "12345678",
"serial_id_gas": None,
},
),
(
"5S",
{

View File

@ -512,6 +512,76 @@ async def test_luxembourg_meter(
)
async def test_eonhu_meter(
hass: HomeAssistant, dsmr_connection_fixture: tuple[MagicMock, MagicMock, MagicMock]
) -> None:
"""Test if v5 meter is correctly parsed."""
(connection_factory, transport, protocol) = dsmr_connection_fixture
entry_data = {
"port": "/dev/ttyUSB0",
"dsmr_version": "5EONHU",
"serial_id": "1234",
}
entry_options = {
"time_between_update": 0,
}
telegram = Telegram()
telegram.add(
ELECTRICITY_IMPORTED_TOTAL,
CosemObject(
(0, 0),
[{"value": Decimal("123.456"), "unit": UnitOfEnergy.KILO_WATT_HOUR}],
),
"ELECTRICITY_IMPORTED_TOTAL",
)
telegram.add(
ELECTRICITY_EXPORTED_TOTAL,
CosemObject(
(0, 0),
[{"value": Decimal("654.321"), "unit": UnitOfEnergy.KILO_WATT_HOUR}],
),
"ELECTRICITY_EXPORTED_TOTAL",
)
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]
# simulate a telegram pushed from the smartmeter and parsed by dsmr_parser
telegram_callback(telegram)
# after receiving telegram entities need to have the chance to be created
await hass.async_block_till_done()
active_tariff = hass.states.get("sensor.electricity_meter_energy_consumption_total")
assert active_tariff.state == "123.456"
assert active_tariff.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.ENERGY
assert (
active_tariff.attributes.get(ATTR_STATE_CLASS)
== SensorStateClass.TOTAL_INCREASING
)
assert (
active_tariff.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
== UnitOfEnergy.KILO_WATT_HOUR
)
active_tariff = hass.states.get("sensor.electricity_meter_energy_production_total")
assert active_tariff.state == "654.321"
assert (
active_tariff.attributes.get("unit_of_measurement")
== UnitOfEnergy.KILO_WATT_HOUR
)
async def test_belgian_meter(
hass: HomeAssistant, dsmr_connection_fixture: tuple[MagicMock, MagicMock, MagicMock]
) -> None: