Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added E.ON HUNGARY specification #134

Merged
merged 8 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions dsmr_parser/clients/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ def _create_dsmr_protocol(dsmr_version, telegram_callback, protocol, loop=None,
elif dsmr_version == 'ISKRA_IE':
specification = telegram_specifications.ISKRA_IE
serial_settings = SERIAL_SETTINGS_V5
elif dsmr_version == '5EONHU':
specification = telegram_specifications.EON_HUNGARY
serial_settings = SERIAL_SETTINGS_V5
else:
raise NotImplementedError("No telegram parser found for version: %s",
dsmr_version)
Expand Down
7 changes: 6 additions & 1 deletion dsmr_parser/clients/socket_.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ def read(self):
continue

for data in lines:
self.telegram_buffer.append(data.decode('ascii'))
try:
self.telegram_buffer.append(data.decode('ascii'))
except UnicodeDecodeError:
# Some garbage came through the channel
# E.g.: Happens at EON_HUNGARY, but only once at the start of the socket.
logger.error('Failed to parse telegram due to unicode decode error')

for telegram in self.telegram_buffer.get_all():
try:
Expand Down
24 changes: 23 additions & 1 deletion dsmr_parser/obis_name_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,29 @@
obis.Q3D_EQUIPMENT_IDENTIFIER: 'Q3D_EQUIPMENT_IDENTIFIER',
obis.Q3D_EQUIPMENT_STATE: 'Q3D_EQUIPMENT_STATE',
obis.Q3D_EQUIPMENT_SERIALNUMBER: 'Q3D_EQUIPMENT_SERIALNUMBER',
obis.BELGIUM_MBUS2_DEVICE_TYPE: 'BELGIUM_MBUS2_DEVICE_TYPE'
obis.BELGIUM_MBUS2_DEVICE_TYPE: 'BELGIUM_MBUS2_DEVICE_TYPE',
obis.EON_HU_ELECTRICITY_DELIVERED_TARIFF_3: 'EON_HU_ELECTRICITY_DELIVERED_TARIFF_3',
obis.EON_HU_ELECTRICITY_DELIVERED_TARIFF_4: 'EON_HU_ELECTRICITY_DELIVERED_TARIFF_4',
obis.EON_HU_ELECTRICITY_USED_TARIFF_3: 'EON_HU_ELECTRICITY_USED_TARIFF_3',
obis.EON_HU_ELECTRICITY_USED_TARIFF_4: 'EON_HU_ELECTRICITY_USED_TARIFF_4',
obis.EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q1: 'EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q1',
obis.EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q2: 'EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q2',
obis.EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q3: 'EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q3',
obis.EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q4: 'EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q4',
obis.EON_HU_ELECTRICITY_COMBINED: 'EON_HU_ELECTRICITY_COMBINED',
obis.EON_HU_INSTANTANEOUS_POWER_FACTOR_TOTAL: 'EON_HU_INSTANTANEOUS_POWER_FACTOR_TOTAL',
obis.EON_HU_INSTANTANEOUS_POWER_FACTOR_L1: 'EON_HU_INSTANTANEOUS_POWER_FACTOR_L1',
obis.EON_HU_INSTANTANEOUS_POWER_FACTOR_L2: 'EON_HU_INSTANTANEOUS_POWER_FACTOR_L2',
obis.EON_HU_INSTANTANEOUS_POWER_FACTOR_L3: 'EON_HU_INSTANTANEOUS_POWER_FACTOR_L3',
obis.EON_HU_FREQUENCY: 'EON_HU_FREQUENCY',
obis.EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q1: 'EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q1',
obis.EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q2: 'EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q2',
obis.EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q3: 'EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q3',
obis.EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q4: 'EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q4',
obis.EON_HU_MAX_POWER_ON_L1: 'EON_HU_MAX_POWER_ON_L1',
obis.EON_HU_MAX_POWER_ON_L2: 'EON_HU_MAX_POWER_ON_L2',
obis.EON_HU_MAX_POWER_ON_L3: 'EON_HU_MAX_POWER_ON_L3',
obis.EON_HU_LAST_MONTH_DATA: 'EON_HU_LAST_MONTH_DATA'
}

REVERSE_EN = dict([(v, k) for k, v in EN.items()])
24 changes: 24 additions & 0 deletions dsmr_parser/obis_references.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,27 @@
Q3D_EQUIPMENT_IDENTIFIER = r'^\d-\d:0\.0\.0.+?\r\n' # Logical device name
Q3D_EQUIPMENT_STATE = r'^\d-\d:96\.5\.5.+?\r\n' # Device state (hexadecimal)
Q3D_EQUIPMENT_SERIALNUMBER = r'^\d-\d:96\.1\.255.+?\r\n' # Device Serialnumber

# EON Hungary
EON_HU_ELECTRICITY_USED_TARIFF_3 = r'^\d-\d:1\.8\.3.+?\r\n'
EON_HU_ELECTRICITY_USED_TARIFF_4 = r'^\d-\d:1\.8\.4.+?\r\n'
EON_HU_ELECTRICITY_DELIVERED_TARIFF_3 = r'^\d-\d:2\.8\.3.+?\r\n'
EON_HU_ELECTRICITY_DELIVERED_TARIFF_4 = r'^\d-\d:2\.8\.4.+?\r\n'
EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q1 = r'^\d-\d:5\.8\.0.+?\r\n'
EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q2 = r'^\d-\d:6\.8\.0.+?\r\n'
EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q3 = r'^\d-\d:7\.8\.0.+?\r\n'
EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q4 = r'^\d-\d:8\.8\.0.+?\r\n'
EON_HU_ELECTRICITY_COMBINED = r'^\d-\d:15\.8\.0.+?\r\n'
EON_HU_INSTANTANEOUS_POWER_FACTOR_TOTAL = r'^\d-\d:13\.7\.0.+?\r\n'
EON_HU_INSTANTANEOUS_POWER_FACTOR_L1 = r'^\d-\d:33\.7\.0.+?\r\n'
EON_HU_INSTANTANEOUS_POWER_FACTOR_L2 = r'^\d-\d:53\.7\.0.+?\r\n'
EON_HU_INSTANTANEOUS_POWER_FACTOR_L3 = r'^\d-\d:73\.7\.0.+?\r\n'
EON_HU_FREQUENCY = r'^\d-\d:14\.7\.0.+?\r\n'
EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q1 = r'^\d-\d:5\.7\.0.+?\r\n'
EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q2 = r'^\d-\d:6\.7\.0.+?\r\n'
EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q3 = r'^\d-\d:7\.7\.0.+?\r\n'
EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q4 = r'^\d-\d:8\.7\.0.+?\r\n'
EON_HU_MAX_POWER_ON_L1 = r'^\d-\d:31\.4\.0.+?\r\n'
EON_HU_MAX_POWER_ON_L2 = r'^\d-\d:51\.4\.0.+?\r\n'
EON_HU_MAX_POWER_ON_L3 = r'^\d-\d:71\.4\.0.+?\r\n'
EON_HU_LAST_MONTH_DATA = r'^\d-\d:98\.1\.0.+?\r\n'
57 changes: 57 additions & 0 deletions dsmr_parser/telegram_specifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,60 @@
obis.EQUIPMENT_IDENTIFIER: CosemParser(ValueParser(str)),
}
}

EON_HUNGARY = {
# Revision: 2023.02.10
# Based on V5
# Reference: https://www.eon.hu/content/dam/eon/eon-hungary/documents/Lakossagi/aram/muszaki-ugyek/p1_port%20felhaszn_interfesz_taj_%2020230210.pdf
'checksum_support': True,
'objects': {
obis.P1_MESSAGE_TIMESTAMP: CosemParser(ValueParser(timestamp)),
obis.LUXEMBOURG_EQUIPMENT_IDENTIFIER: CosemParser(ValueParser(str)), # "COSEM logical equipment name"
obis.EQUIPMENT_IDENTIFIER_GAS: CosemParser(ValueParser(str)), # This obis is already defined, so it is not possible to "rename" it to "EQUIPMENT_SERIAL_NUMBER"
obis.ELECTRICITY_ACTIVE_TARIFF: CosemParser(ValueParser(str)),
obis.ACTUAL_SWITCH_POSITION: CosemParser(ValueParser(str)), # This seems to be wrong in documentation, it's not 0-0:96.50.68, but 0-0:96.3.10
obis.ACTUAL_TRESHOLD_ELECTRICITY: CosemParser(ValueParser(Decimal)), # This obis is already duplicated, so it will show up as "BELGIUM_MAX_POWER_PER_PHASE"
obis.ELECTRICITY_IMPORTED_TOTAL: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_USED_TARIFF_1: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_USED_TARIFF_2: CosemParser(ValueParser(Decimal)),
obis.EON_HU_ELECTRICITY_USED_TARIFF_3: CosemParser(ValueParser(Decimal)),
obis.EON_HU_ELECTRICITY_USED_TARIFF_4: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_EXPORTED_TOTAL: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_DELIVERED_TARIFF_1: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_DELIVERED_TARIFF_2: CosemParser(ValueParser(Decimal)),
obis.EON_HU_ELECTRICITY_DELIVERED_TARIFF_3: CosemParser(ValueParser(Decimal)),
obis.EON_HU_ELECTRICITY_DELIVERED_TARIFF_4: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_REACTIVE_IMPORTED_TOTAL: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_REACTIVE_EXPORTED_TOTAL: CosemParser(ValueParser(Decimal)),
obis.EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q1: CosemParser(ValueParser(Decimal)),
obis.EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q2: CosemParser(ValueParser(Decimal)),
obis.EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q3: CosemParser(ValueParser(Decimal)),
obis.EON_HU_ELECTRICITY_REACTIVE_TOTAL_Q4: CosemParser(ValueParser(Decimal)),
obis.EON_HU_ELECTRICITY_COMBINED: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_VOLTAGE_L1: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_VOLTAGE_L2: CosemParser(ValueParser(Decimal)), # Only with 3 phase meters
obis.INSTANTANEOUS_VOLTAGE_L3: CosemParser(ValueParser(Decimal)), # Only with 3 phase meters
obis.INSTANTANEOUS_CURRENT_L1: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_CURRENT_L2: CosemParser(ValueParser(Decimal)), # Only with 3 phase meters
obis.INSTANTANEOUS_CURRENT_L3: CosemParser(ValueParser(Decimal)), # Only with 3 phase meters
obis.EON_HU_INSTANTANEOUS_POWER_FACTOR_TOTAL: CosemParser(ValueParser(Decimal)),
obis.EON_HU_INSTANTANEOUS_POWER_FACTOR_L1: CosemParser(ValueParser(Decimal)),
obis.EON_HU_INSTANTANEOUS_POWER_FACTOR_L2: CosemParser(ValueParser(Decimal)), # Only with 3 phase meters
obis.EON_HU_INSTANTANEOUS_POWER_FACTOR_L3: CosemParser(ValueParser(Decimal)), # Only with 3 phase meters
obis.EON_HU_FREQUENCY: CosemParser(ValueParser(Decimal)),
obis.CURRENT_ELECTRICITY_USAGE: CosemParser(ValueParser(Decimal)),
obis.CURRENT_ELECTRICITY_DELIVERY: CosemParser(ValueParser(Decimal)),
obis.EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q1: CosemParser(ValueParser(Decimal)),
obis.EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q2: CosemParser(ValueParser(Decimal)),
obis.EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q3: CosemParser(ValueParser(Decimal)),
obis.EON_HU_INSTANTANEOUS_REACTIVE_POWER_Q4: CosemParser(ValueParser(Decimal)),
obis.EON_HU_MAX_POWER_ON_L1: CosemParser(ValueParser(Decimal)),
obis.EON_HU_MAX_POWER_ON_L2: CosemParser(ValueParser(Decimal)), # Only with 3 phase meters
obis.EON_HU_MAX_POWER_ON_L3: CosemParser(ValueParser(Decimal)), # Only with 3 phase meters
# This is a list of last month data (on last day of last month @ 23:59:59),
# But it is not clear that what are the elements of the list.
# This is not well documented enough, so it is ignored for now.
# obis.EON_HU_LAST_MONTH_DATA:
obis.TEXT_MESSAGE: CosemParser(ValueParser(str))
}
}
52 changes: 52 additions & 0 deletions test/example_telegrams.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,3 +311,55 @@
'0-1:96.1.1()\r\n'
'!AD3B\r\n'
)

# V5 telegram of EON in Hungary
TELEGRAM_V5_EON_HU = (
'/SAG5SAG-METER\r\n'
'\r\n'
'0-0:1.0.0(230724150730S)\r\n'
'0-0:42.0.0(53414733303832323030303032313630)\r\n'
'0-0:96.1.0(383930303832323030303032313630)\r\n'
'0-0:96.14.0(0001)\r\n'
'0-0:96.3.10(1)\r\n'
'0-0:17.0.0(90.000*kW)\r\n'
'1-0:1.8.0(000173.640*kWh)\r\n'
'1-0:1.8.1(000047.719*kWh)\r\n'
'1-0:1.8.2(000125.921*kWh)\r\n'
'1-0:1.8.3(000000.000*kWh)\r\n'
'1-0:1.8.4(000000.000*kWh)\r\n'
'1-0:2.8.0(000627.177*kWh)\r\n'
'1-0:2.8.1(000401.829*kWh)\r\n'
'1-0:2.8.2(000225.348*kWh)\r\n'
'1-0:2.8.3(000000.000*kWh)\r\n'
'1-0:2.8.4(000000.000*kWh)\r\n'
'1-0:3.8.0(000000.123*kvarh)\r\n'
'1-0:4.8.0(000303.131*kvarh)\r\n'
'1-0:5.8.0(000000.668*kvarh)\r\n'
'1-0:6.8.0(000000.071*kvarh)\r\n'
'1-0:7.8.0(000160.487*kvarh)\r\n'
'1-0:8.8.0(000143.346*kvarh)\r\n'
'1-0:15.8.0(000800.817*kWh)\r\n'
'1-0:32.7.0(240.4*V)\r\n'
'1-0:52.7.0(239.1*V)\r\n'
'1-0:72.7.0(241.2*V)\r\n'
'1-0:31.7.0(003*A)\r\n'
'1-0:51.7.0(004*A)\r\n'
'1-0:71.7.0(003*A)\r\n'
'1-0:13.7.0(4.556)\r\n'
'1-0:33.7.0(4.591)\r\n'
'1-0:53.7.0(4.542)\r\n'
'1-0:73.7.0(4.552)\r\n'
'1-0:14.7.0(50.00*Hz)\r\n'
'1-0:1.7.0(00.000*kW)\r\n'
'1-0:2.7.0(02.601*kW)\r\n'
'1-0:5.7.0(00.000*kvar)\r\n'
'1-0:6.7.0(00.000*kvar)\r\n'
'1-0:7.7.0(00.504*kvar)\r\n'
'1-0:8.7.0(00.000*kvar)\r\n'
'1-0:31.4.0(200.00*A)\r\n'
'1-0:51.4.0(200.00*A)\r\n'
'1-0:71.4.0(200.00*A)\r\n'
'0-0:98.1.0(230701000000S)(000040.777*kWh)(000008.950*kWh)(000031.827*kWh)(000142.250*kWh)(000111.164*kWh)(000031.086*kWh)(000000.030*kvarh)(000073.988*kvarh)(000000.205*kvarh)(000000.048*kvarh)(000039.199*kvarh)(000035.020*kvarh)(000183.027*kWh)(03.564*kW)(02.156*kW)(03.564*kW)(04.104*kW)(04.104*kW)(03.400*kW)\r\n'
'0-0:96.13.0()\r\n'
'!99DA\r\n'
)
Loading
Loading