mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
parent
ab1e1c06b6
commit
a85bb98743
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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":
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -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(
|
||||
|
@ -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",
|
||||
{
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user