From df59f3a4989bacb70e8748b4ad56f51b14c8f011 Mon Sep 17 00:00:00 2001 From: Gunnar Klauberg Date: Sun, 14 Nov 2021 21:49:43 +0000 Subject: [PATCH] decode latin1 and added ELECTRICITY_EXPORTED_TOTAL --- dsmr_parser/clients/protocol.py | 66 ++++++-------- dsmr_parser/obis_name_mapping.py | 102 ++++++++++----------- dsmr_parser/obis_references.py | 119 ++++++++++++------------- dsmr_parser/telegram_specifications.py | 94 +++++++++---------- 4 files changed, 173 insertions(+), 208 deletions(-) diff --git a/dsmr_parser/clients/protocol.py b/dsmr_parser/clients/protocol.py index 3b4c062..208ed1b 100644 --- a/dsmr_parser/clients/protocol.py +++ b/dsmr_parser/clients/protocol.py @@ -10,26 +10,23 @@ from dsmr_parser import telegram_specifications from dsmr_parser.clients.telegram_buffer import TelegramBuffer from dsmr_parser.exceptions import ParseError, InvalidChecksumError from dsmr_parser.parsers import TelegramParser -from dsmr_parser.clients.settings import ( - SERIAL_SETTINGS_V2_2, - SERIAL_SETTINGS_V4, - SERIAL_SETTINGS_V5, -) +from dsmr_parser.clients.settings import SERIAL_SETTINGS_V2_2, \ + SERIAL_SETTINGS_V4, SERIAL_SETTINGS_V5 def create_dsmr_protocol(dsmr_version, telegram_callback, loop=None, **kwargs): """Creates a DSMR asyncio protocol.""" - if dsmr_version == "2.2": + if dsmr_version == '2.2': specification = telegram_specifications.V2_2 serial_settings = SERIAL_SETTINGS_V2_2 - elif dsmr_version == "4": + elif dsmr_version == '4': specification = telegram_specifications.V4 serial_settings = SERIAL_SETTINGS_V4 - elif dsmr_version == "5": + elif dsmr_version == '5': specification = telegram_specifications.V5 serial_settings = SERIAL_SETTINGS_V5 - elif dsmr_version == "5B": + elif dsmr_version == '5B': specification = telegram_specifications.BELGIUM_FLUVIUS serial_settings = SERIAL_SETTINGS_V5 elif dsmr_version == "5L": @@ -42,17 +39,11 @@ def create_dsmr_protocol(dsmr_version, telegram_callback, loop=None, **kwargs): specification = telegram_specifications.Q3D serial_settings = SERIAL_SETTINGS_V5 else: - raise NotImplementedError( - "No telegram parser found for version: %s", dsmr_version - ) + raise NotImplementedError("No telegram parser found for version: %s", + dsmr_version) - protocol = partial( - DSMRProtocol, - loop, - TelegramParser(specification), - telegram_callback=telegram_callback, - **kwargs - ) + protocol = partial(DSMRProtocol, loop, TelegramParser(specification), + telegram_callback=telegram_callback, **kwargs) return protocol, serial_settings @@ -60,26 +51,22 @@ def create_dsmr_protocol(dsmr_version, telegram_callback, loop=None, **kwargs): def create_dsmr_reader(port, dsmr_version, telegram_callback, loop=None): """Creates a DSMR asyncio protocol coroutine using serial port.""" protocol, serial_settings = create_dsmr_protocol( - dsmr_version, telegram_callback, loop=None - ) - serial_settings["url"] = port + dsmr_version, telegram_callback, loop=None) + serial_settings['url'] = port conn = create_serial_connection(loop, protocol, **serial_settings) return conn -def create_tcp_dsmr_reader( - host, port, dsmr_version, telegram_callback, loop=None, keep_alive_interval=None -): +def create_tcp_dsmr_reader(host, port, dsmr_version, + telegram_callback, loop=None, + keep_alive_interval=None): """Creates a DSMR asyncio protocol coroutine using TCP connection.""" if not loop: loop = asyncio.get_event_loop() protocol, _ = create_dsmr_protocol( - dsmr_version, - telegram_callback, - loop=loop, - keep_alive_interval=keep_alive_interval, - ) + dsmr_version, telegram_callback, loop=loop, + keep_alive_interval=keep_alive_interval) conn = loop.create_connection(protocol, host, port) return conn @@ -90,9 +77,8 @@ class DSMRProtocol(asyncio.Protocol): transport = None telegram_callback = None - def __init__( - self, loop, telegram_parser, telegram_callback=None, keep_alive_interval=None - ): + def __init__(self, loop, telegram_parser, + telegram_callback=None, keep_alive_interval=None): """Initialize class.""" self.loop = loop self.log = logging.getLogger(__name__) @@ -109,7 +95,7 @@ class DSMRProtocol(asyncio.Protocol): def connection_made(self, transport): """Just logging for now.""" self.transport = transport - self.log.debug("connected") + self.log.debug('connected') self._active = False if self.loop and self._keep_alive_interval: self.loop.call_later(self._keep_alive_interval, self.keep_alive) @@ -118,7 +104,7 @@ class DSMRProtocol(asyncio.Protocol): """Add incoming data to buffer.""" data = data.decode("latin1") self._active = True - self.log.debug("received data: %s", data) + self.log.debug('received data: %s', data) self.telegram_buffer.append(data) for telegram in self.telegram_buffer.get_all(): @@ -126,26 +112,26 @@ class DSMRProtocol(asyncio.Protocol): def keep_alive(self): if self._active: - self.log.debug("keep-alive checked") + self.log.debug('keep-alive checked') self._active = False if self.loop: self.loop.call_later(self._keep_alive_interval, self.keep_alive) else: - self.log.warning("keep-alive check failed") + self.log.warning('keep-alive check failed') if self.transport: self.transport.close() def connection_lost(self, exc): """Stop when connection is lost.""" if exc: - self.log.exception("disconnected due to exception", exc_info=exc) + self.log.exception('disconnected due to exception', exc_info=exc) else: - self.log.info("disconnected because of close/abort.") + self.log.info('disconnected because of close/abort.') self._closed.set() def handle_telegram(self, telegram): """Send off parsed telegram to handling callback.""" - self.log.debug("got telegram: %s", telegram) + self.log.debug('got telegram: %s', telegram) try: parsed_telegram = self.telegram_parser.parse(telegram) diff --git a/dsmr_parser/obis_name_mapping.py b/dsmr_parser/obis_name_mapping.py index 5a05f00..87c720d 100644 --- a/dsmr_parser/obis_name_mapping.py +++ b/dsmr_parser/obis_name_mapping.py @@ -8,57 +8,57 @@ This module contains a mapping of obis references to names. """ EN = { - obis.P1_MESSAGE_HEADER: "P1_MESSAGE_HEADER", - obis.P1_MESSAGE_TIMESTAMP: "P1_MESSAGE_TIMESTAMP", - obis.ELECTRICITY_IMPORTED_TOTAL: "ELECTRICITY_IMPORTED_TOTAL", - obis.ELECTRICITY_USED_TARIFF_1: "ELECTRICITY_USED_TARIFF_1", - obis.ELECTRICITY_USED_TARIFF_2: "ELECTRICITY_USED_TARIFF_2", - obis.ELECTRICITY_EXPORTED_TOTAL: "ELECTRICITY_EXPORTED_TOTAL", - obis.ELECTRICITY_DELIVERED_TARIFF_1: "ELECTRICITY_DELIVERED_TARIFF_1", - obis.ELECTRICITY_DELIVERED_TARIFF_2: "ELECTRICITY_DELIVERED_TARIFF_2", - obis.ELECTRICITY_ACTIVE_TARIFF: "ELECTRICITY_ACTIVE_TARIFF", - obis.EQUIPMENT_IDENTIFIER: "EQUIPMENT_IDENTIFIER", - obis.CURRENT_ELECTRICITY_USAGE: "CURRENT_ELECTRICITY_USAGE", - obis.CURRENT_ELECTRICITY_DELIVERY: "CURRENT_ELECTRICITY_DELIVERY", - obis.LONG_POWER_FAILURE_COUNT: "LONG_POWER_FAILURE_COUNT", - obis.SHORT_POWER_FAILURE_COUNT: "SHORT_POWER_FAILURE_COUNT", - obis.POWER_EVENT_FAILURE_LOG: "POWER_EVENT_FAILURE_LOG", - obis.VOLTAGE_SAG_L1_COUNT: "VOLTAGE_SAG_L1_COUNT", - obis.VOLTAGE_SAG_L2_COUNT: "VOLTAGE_SAG_L2_COUNT", - obis.VOLTAGE_SAG_L3_COUNT: "VOLTAGE_SAG_L3_COUNT", - obis.VOLTAGE_SWELL_L1_COUNT: "VOLTAGE_SWELL_L1_COUNT", - obis.VOLTAGE_SWELL_L2_COUNT: "VOLTAGE_SWELL_L2_COUNT", - obis.VOLTAGE_SWELL_L3_COUNT: "VOLTAGE_SWELL_L3_COUNT", - obis.INSTANTANEOUS_VOLTAGE_L1: "INSTANTANEOUS_VOLTAGE_L1", - obis.INSTANTANEOUS_VOLTAGE_L2: "INSTANTANEOUS_VOLTAGE_L2", - obis.INSTANTANEOUS_VOLTAGE_L3: "INSTANTANEOUS_VOLTAGE_L3", - obis.INSTANTANEOUS_CURRENT_L1: "INSTANTANEOUS_CURRENT_L1", - obis.INSTANTANEOUS_CURRENT_L2: "INSTANTANEOUS_CURRENT_L2", - obis.INSTANTANEOUS_CURRENT_L3: "INSTANTANEOUS_CURRENT_L3", - obis.TEXT_MESSAGE_CODE: "TEXT_MESSAGE_CODE", - obis.TEXT_MESSAGE: "TEXT_MESSAGE", - obis.DEVICE_TYPE: "DEVICE_TYPE", - obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE: "INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE", - obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE: "INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE", - obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE: "INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE", - obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE: "INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE", - obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE: "INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE", - obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE: "INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE", - obis.EQUIPMENT_IDENTIFIER_GAS: "EQUIPMENT_IDENTIFIER_GAS", - obis.HOURLY_GAS_METER_READING: "HOURLY_GAS_METER_READING", - obis.GAS_METER_READING: "GAS_METER_READING", - obis.ACTUAL_TRESHOLD_ELECTRICITY: "ACTUAL_TRESHOLD_ELECTRICITY", - obis.ACTUAL_SWITCH_POSITION: "ACTUAL_SWITCH_POSITION", - obis.VALVE_POSITION_GAS: "VALVE_POSITION_GAS", - obis.BELGIUM_HOURLY_GAS_METER_READING: "BELGIUM_HOURLY_GAS_METER_READING", - obis.LUXEMBOURG_EQUIPMENT_IDENTIFIER: "LUXEMBOURG_EQUIPMENT_IDENTIFIER", - obis.LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL: "LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL", - obis.LUXEMBOURG_ELECTRICITY_DELIVERED_TARIFF_GLOBAL: "LUXEMBOURG_ELECTRICITY_DELIVERED_TARIFF_GLOBAL", - obis.SWEDEN_ELECTRICITY_USED_TARIFF_GLOBAL: "SWEDEN_ELECTRICITY_USED_TARIFF_GLOBAL", - obis.SWEDEN_ELECTRICITY_DELIVERED_TARIFF_GLOBAL: "SWEDEN_ELECTRICITY_DELIVERED_TARIFF_GLOBAL", - obis.Q3D_EQUIPMENT_IDENTIFIER: "Q3D_EQUIPMENT_IDENTIFIER", - obis.Q3D_EQUIPMENT_STATE: "Q3D_EQUIPMENT_STATE", - obis.Q3D_EQUIPMENT_SERIALNUMBER: "Q3D_EQUIPMENT_SERIALNUMBER", + obis.P1_MESSAGE_HEADER: 'P1_MESSAGE_HEADER', + obis.P1_MESSAGE_TIMESTAMP: 'P1_MESSAGE_TIMESTAMP', + obis.ELECTRICITY_IMPORTED_TOTAL: 'ELECTRICITY_IMPORTED_TOTAL', + obis.ELECTRICITY_USED_TARIFF_1: 'ELECTRICITY_USED_TARIFF_1', + obis.ELECTRICITY_USED_TARIFF_2: 'ELECTRICITY_USED_TARIFF_2', + obis.ELECTRICITY_EXPORTED_TOTAL: 'ELECTRICITY_EXPORTED_TOTAL', + obis.ELECTRICITY_DELIVERED_TARIFF_1: 'ELECTRICITY_DELIVERED_TARIFF_1', + obis.ELECTRICITY_DELIVERED_TARIFF_2: 'ELECTRICITY_DELIVERED_TARIFF_2', + obis.ELECTRICITY_ACTIVE_TARIFF: 'ELECTRICITY_ACTIVE_TARIFF', + obis.EQUIPMENT_IDENTIFIER: 'EQUIPMENT_IDENTIFIER', + obis.CURRENT_ELECTRICITY_USAGE: 'CURRENT_ELECTRICITY_USAGE', + obis.CURRENT_ELECTRICITY_DELIVERY: 'CURRENT_ELECTRICITY_DELIVERY', + obis.LONG_POWER_FAILURE_COUNT: 'LONG_POWER_FAILURE_COUNT', + obis.SHORT_POWER_FAILURE_COUNT: 'SHORT_POWER_FAILURE_COUNT', + obis.POWER_EVENT_FAILURE_LOG: 'POWER_EVENT_FAILURE_LOG', + obis.VOLTAGE_SAG_L1_COUNT: 'VOLTAGE_SAG_L1_COUNT', + obis.VOLTAGE_SAG_L2_COUNT: 'VOLTAGE_SAG_L2_COUNT', + obis.VOLTAGE_SAG_L3_COUNT: 'VOLTAGE_SAG_L3_COUNT', + obis.VOLTAGE_SWELL_L1_COUNT: 'VOLTAGE_SWELL_L1_COUNT', + obis.VOLTAGE_SWELL_L2_COUNT: 'VOLTAGE_SWELL_L2_COUNT', + obis.VOLTAGE_SWELL_L3_COUNT: 'VOLTAGE_SWELL_L3_COUNT', + obis.INSTANTANEOUS_VOLTAGE_L1: 'INSTANTANEOUS_VOLTAGE_L1', + obis.INSTANTANEOUS_VOLTAGE_L2: 'INSTANTANEOUS_VOLTAGE_L2', + obis.INSTANTANEOUS_VOLTAGE_L3: 'INSTANTANEOUS_VOLTAGE_L3', + obis.INSTANTANEOUS_CURRENT_L1: 'INSTANTANEOUS_CURRENT_L1', + obis.INSTANTANEOUS_CURRENT_L2: 'INSTANTANEOUS_CURRENT_L2', + obis.INSTANTANEOUS_CURRENT_L3: 'INSTANTANEOUS_CURRENT_L3', + obis.TEXT_MESSAGE_CODE: 'TEXT_MESSAGE_CODE', + obis.TEXT_MESSAGE: 'TEXT_MESSAGE', + obis.DEVICE_TYPE: 'DEVICE_TYPE', + obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE: 'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE: 'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE: 'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE: 'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE: 'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE', + obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE: 'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE', + obis.EQUIPMENT_IDENTIFIER_GAS: 'EQUIPMENT_IDENTIFIER_GAS', + obis.HOURLY_GAS_METER_READING: 'HOURLY_GAS_METER_READING', + obis.GAS_METER_READING: 'GAS_METER_READING', + obis.ACTUAL_TRESHOLD_ELECTRICITY: 'ACTUAL_TRESHOLD_ELECTRICITY', + obis.ACTUAL_SWITCH_POSITION: 'ACTUAL_SWITCH_POSITION', + obis.VALVE_POSITION_GAS: 'VALVE_POSITION_GAS', + obis.BELGIUM_HOURLY_GAS_METER_READING: 'BELGIUM_HOURLY_GAS_METER_READING', + obis.LUXEMBOURG_EQUIPMENT_IDENTIFIER: 'LUXEMBOURG_EQUIPMENT_IDENTIFIER', + obis.LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL: 'LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL', + obis.LUXEMBOURG_ELECTRICITY_DELIVERED_TARIFF_GLOBAL: 'LUXEMBOURG_ELECTRICITY_DELIVERED_TARIFF_GLOBAL', + obis.SWEDEN_ELECTRICITY_USED_TARIFF_GLOBAL: 'SWEDEN_ELECTRICITY_USED_TARIFF_GLOBAL', + obis.SWEDEN_ELECTRICITY_DELIVERED_TARIFF_GLOBAL: 'SWEDEN_ELECTRICITY_DELIVERED_TARIFF_GLOBAL', + obis.Q3D_EQUIPMENT_IDENTIFIER: 'Q3D_EQUIPMENT_IDENTIFIER', + obis.Q3D_EQUIPMENT_STATE: 'Q3D_EQUIPMENT_STATE', + obis.Q3D_EQUIPMENT_SERIALNUMBER: 'Q3D_EQUIPMENT_SERIALNUMBER', } REVERSE_EN = dict([(v, k) for k, v in EN.items()]) diff --git a/dsmr_parser/obis_references.py b/dsmr_parser/obis_references.py index 02e1e33..ad3bd98 100644 --- a/dsmr_parser/obis_references.py +++ b/dsmr_parser/obis_references.py @@ -6,76 +6,69 @@ refactored to full line signatures to maintain backwards compatibility. Might be refactored in a backwards incompatible way as soon as proper telegram objects are introduced. """ -P1_MESSAGE_HEADER = r"\d-\d:0\.2\.8.+?\r\n" -P1_MESSAGE_TIMESTAMP = r"\d-\d:1\.0\.0.+?\r\n" -ELECTRICITY_IMPORTED_TOTAL = r"\d-\d:1\.8\.0.+?\r\n" -ELECTRICITY_USED_TARIFF_1 = r"\d-\d:1\.8\.1.+?\r\n" -ELECTRICITY_USED_TARIFF_2 = r"\d-\d:1\.8\.2.+?\r\n" -ELECTRICITY_EXPORTED_TOTAL = r"\d-\d:2\.8\.0.+?\r\n" -ELECTRICITY_DELIVERED_TARIFF_1 = r"\d-\d:2\.8\.1.+?\r\n" -ELECTRICITY_DELIVERED_TARIFF_2 = r"\d-\d:2\.8\.2.+?\r\n" -ELECTRICITY_ACTIVE_TARIFF = r"\d-\d:96\.14\.0.+?\r\n" -EQUIPMENT_IDENTIFIER = r"\d-\d:96\.1\.1.+?\r\n" -CURRENT_ELECTRICITY_USAGE = r"\d-\d:1\.7\.0.+?\r\n" -CURRENT_ELECTRICITY_DELIVERY = r"\d-\d:2\.7\.0.+?\r\n" -LONG_POWER_FAILURE_COUNT = r"96\.7\.9.+?\r\n" -SHORT_POWER_FAILURE_COUNT = r"96\.7\.21.+?\r\n" -POWER_EVENT_FAILURE_LOG = r"99\.97\.0.+?\r\n" -VOLTAGE_SAG_L1_COUNT = r"\d-\d:32\.32\.0.+?\r\n" -VOLTAGE_SAG_L2_COUNT = r"\d-\d:52\.32\.0.+?\r\n" -VOLTAGE_SAG_L3_COUNT = r"\d-\d:72\.32\.0.+?\r\n" -VOLTAGE_SWELL_L1_COUNT = r"\d-\d:32\.36\.0.+?\r\n" -VOLTAGE_SWELL_L2_COUNT = r"\d-\d:52\.36\.0.+?\r\n" -VOLTAGE_SWELL_L3_COUNT = r"\d-\d:72\.36\.0.+?\r\n" -INSTANTANEOUS_VOLTAGE_L1 = r"\d-\d:32\.7\.0.+?\r\n" -INSTANTANEOUS_VOLTAGE_L2 = r"\d-\d:52\.7\.0.+?\r\n" -INSTANTANEOUS_VOLTAGE_L3 = r"\d-\d:72\.7\.0.+?\r\n" -INSTANTANEOUS_CURRENT_L1 = r"\d-\d:31\.7\.0.+?\r\n" -INSTANTANEOUS_CURRENT_L2 = r"\d-\d:51\.7\.0.+?\r\n" -INSTANTANEOUS_CURRENT_L3 = r"\d-\d:71\.7\.0.+?\r\n" -TEXT_MESSAGE_CODE = r"\d-\d:96\.13\.1.+?\r\n" -TEXT_MESSAGE = r"\d-\d:96\.13\.0.+?\r\n" -DEVICE_TYPE = r"\d-\d:24\.1\.0.+?\r\n" -INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE = r"\d-\d:21\.7\.0.+?\r\n" -INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE = r"\d-\d:41\.7\.0.+?\r\n" -INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE = r"\d-\d:61\.7\.0.+?\r\n" -INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE = r"\d-\d:22\.7\.0.+?\r\n" -INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE = r"\d-\d:42\.7\.0.+?\r\n" -INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE = r"\d-\d:62\.7\.0.+?\r\n" -EQUIPMENT_IDENTIFIER_GAS = r"\d-\d:96\.1\.0.+?\r\n" +P1_MESSAGE_HEADER = r'\d-\d:0\.2\.8.+?\r\n' +P1_MESSAGE_TIMESTAMP = r'\d-\d:1\.0\.0.+?\r\n' +ELECTRICITY_IMPORTED_TOTAL = r'\d-\d:1\.8\.0.+?\r\n' +ELECTRICITY_USED_TARIFF_1 = r'\d-\d:1\.8\.1.+?\r\n' +ELECTRICITY_USED_TARIFF_2 = r'\d-\d:1\.8\.2.+?\r\n' +ELECTRICITY_EXPORTED_TOTAL = r'\d-\d:2\.8\.0.+?\r\n' +ELECTRICITY_DELIVERED_TARIFF_1 = r'\d-\d:2\.8\.1.+?\r\n' +ELECTRICITY_DELIVERED_TARIFF_2 = r'\d-\d:2\.8\.2.+?\r\n' +ELECTRICITY_ACTIVE_TARIFF = r'\d-\d:96\.14\.0.+?\r\n' +EQUIPMENT_IDENTIFIER = r'\d-\d:96\.1\.1.+?\r\n' +CURRENT_ELECTRICITY_USAGE = r'\d-\d:1\.7\.0.+?\r\n' +CURRENT_ELECTRICITY_DELIVERY = r'\d-\d:2\.7\.0.+?\r\n' +LONG_POWER_FAILURE_COUNT = r'96\.7\.9.+?\r\n' +SHORT_POWER_FAILURE_COUNT = r'96\.7\.21.+?\r\n' +POWER_EVENT_FAILURE_LOG = r'99\.97\.0.+?\r\n' +VOLTAGE_SAG_L1_COUNT = r'\d-\d:32\.32\.0.+?\r\n' +VOLTAGE_SAG_L2_COUNT = r'\d-\d:52\.32\.0.+?\r\n' +VOLTAGE_SAG_L3_COUNT = r'\d-\d:72\.32\.0.+?\r\n' +VOLTAGE_SWELL_L1_COUNT = r'\d-\d:32\.36\.0.+?\r\n' +VOLTAGE_SWELL_L2_COUNT = r'\d-\d:52\.36\.0.+?\r\n' +VOLTAGE_SWELL_L3_COUNT = r'\d-\d:72\.36\.0.+?\r\n' +INSTANTANEOUS_VOLTAGE_L1 = r'\d-\d:32\.7\.0.+?\r\n' +INSTANTANEOUS_VOLTAGE_L2 = r'\d-\d:52\.7\.0.+?\r\n' +INSTANTANEOUS_VOLTAGE_L3 = r'\d-\d:72\.7\.0.+?\r\n' +INSTANTANEOUS_CURRENT_L1 = r'\d-\d:31\.7\.0.+?\r\n' +INSTANTANEOUS_CURRENT_L2 = r'\d-\d:51\.7\.0.+?\r\n' +INSTANTANEOUS_CURRENT_L3 = r'\d-\d:71\.7\.0.+?\r\n' +TEXT_MESSAGE_CODE = r'\d-\d:96\.13\.1.+?\r\n' +TEXT_MESSAGE = r'\d-\d:96\.13\.0.+?\r\n' +DEVICE_TYPE = r'\d-\d:24\.1\.0.+?\r\n' +INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE = r'\d-\d:21\.7\.0.+?\r\n' +INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE = r'\d-\d:41\.7\.0.+?\r\n' +INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE = r'\d-\d:61\.7\.0.+?\r\n' +INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE = r'\d-\d:22\.7\.0.+?\r\n' +INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE = r'\d-\d:42\.7\.0.+?\r\n' +INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE = r'\d-\d:62\.7\.0.+?\r\n' +EQUIPMENT_IDENTIFIER_GAS = r'\d-\d:96\.1\.0.+?\r\n' # TODO differences between gas meter readings in v3 and lower and v4 and up -HOURLY_GAS_METER_READING = r"\d-\d:24\.2\.1.+?\r\n" -GAS_METER_READING = r"\d-\d:24\.3\.0.+?\r\n.+?\r\n" -ACTUAL_TRESHOLD_ELECTRICITY = r"\d-\d:17\.0\.0.+?\r\n" -ACTUAL_SWITCH_POSITION = r"\d-\d:96\.3\.10.+?\r\n" -VALVE_POSITION_GAS = r"\d-\d:24\.4\.0.+?\r\n" +HOURLY_GAS_METER_READING = r'\d-\d:24\.2\.1.+?\r\n' +GAS_METER_READING = r'\d-\d:24\.3\.0.+?\r\n.+?\r\n' +ACTUAL_TRESHOLD_ELECTRICITY = r'\d-\d:17\.0\.0.+?\r\n' +ACTUAL_SWITCH_POSITION = r'\d-\d:96\.3\.10.+?\r\n' +VALVE_POSITION_GAS = r'\d-\d:24\.4\.0.+?\r\n' # TODO 17.0.0 # TODO 96.3.10 -ELECTRICITY_USED_TARIFF_ALL = (ELECTRICITY_USED_TARIFF_1, ELECTRICITY_USED_TARIFF_2) +ELECTRICITY_USED_TARIFF_ALL = ( + ELECTRICITY_USED_TARIFF_1, + ELECTRICITY_USED_TARIFF_2 +) ELECTRICITY_DELIVERED_TARIFF_ALL = ( ELECTRICITY_DELIVERED_TARIFF_1, - ELECTRICITY_DELIVERED_TARIFF_2, + ELECTRICITY_DELIVERED_TARIFF_2 ) # Alternate codes for foreign countries. -BELGIUM_HOURLY_GAS_METER_READING = ( - r"\d-\d:24\.2\.3.+?\r\n" # Different code, same format. -) -LUXEMBOURG_EQUIPMENT_IDENTIFIER = r"\d-\d:42\.0\.0.+?\r\n" # Logical device name -LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL = ( - r"\d-\d:1\.8\.0.+?\r\n" # Total imported energy register (P+) -) -LUXEMBOURG_ELECTRICITY_DELIVERED_TARIFF_GLOBAL = ( - r"\d-\d:2\.8\.0.+?\r\n" # Total exported energy register (P-) -) -SWEDEN_ELECTRICITY_USED_TARIFF_GLOBAL = ( - r"\d-\d:1\.8\.0.+?\r\n" # Total imported energy register (P+) -) -SWEDEN_ELECTRICITY_DELIVERED_TARIFF_GLOBAL = ( - r"\d-\d:2\.8\.0.+?\r\n" # Total exported energy register (P-) -) -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 +BELGIUM_HOURLY_GAS_METER_READING = r'\d-\d:24\.2\.3.+?\r\n' # Different code, same format. +LUXEMBOURG_EQUIPMENT_IDENTIFIER = r'\d-\d:42\.0\.0.+?\r\n' # Logical device name +LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL = r'\d-\d:1\.8\.0.+?\r\n' # Total imported energy register (P+) +LUXEMBOURG_ELECTRICITY_DELIVERED_TARIFF_GLOBAL = r'\d-\d:2\.8\.0.+?\r\n' # Total exported energy register (P-) +SWEDEN_ELECTRICITY_USED_TARIFF_GLOBAL = r'\d-\d:1\.8\.0.+?\r\n' # Total imported energy register (P+) +SWEDEN_ELECTRICITY_DELIVERED_TARIFF_GLOBAL = r'\d-\d:2\.8\.0.+?\r\n' # Total exported energy register (P-) +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 diff --git a/dsmr_parser/telegram_specifications.py b/dsmr_parser/telegram_specifications.py index 77ea49e..00d0c31 100644 --- a/dsmr_parser/telegram_specifications.py +++ b/dsmr_parser/telegram_specifications.py @@ -2,18 +2,9 @@ from decimal import Decimal from copy import deepcopy from dsmr_parser import obis_references as obis -from dsmr_parser.parsers import ( - CosemParser, - ValueParser, - MBusParser, - ProfileGenericParser, -) +from dsmr_parser.parsers import CosemParser, ValueParser, MBusParser, ProfileGenericParser from dsmr_parser.value_types import timestamp -from dsmr_parser.profile_generic_specifications import ( - BUFFER_TYPES, - PG_HEAD_PARSERS, - PG_UNIDENTIFIED_BUFFERTYPE_PARSERS, -) +from dsmr_parser.profile_generic_specifications import BUFFER_TYPES, PG_HEAD_PARSERS, PG_UNIDENTIFIED_BUFFERTYPE_PARSERS """ dsmr_parser.telegram_specifications @@ -24,8 +15,8 @@ how the telegram lines are parsed. """ V2_2 = { - "checksum_support": False, - "objects": { + 'checksum_support': False, + 'objects': { obis.EQUIPMENT_IDENTIFIER: CosemParser(ValueParser(str)), obis.ELECTRICITY_USED_TARIFF_1: CosemParser(ValueParser(Decimal)), obis.ELECTRICITY_USED_TARIFF_2: CosemParser(ValueParser(Decimal)), @@ -50,14 +41,14 @@ V2_2 = { ValueParser(str), # unit, position 5 ValueParser(Decimal), # meter reading, position 6 ), - }, + } } V3 = V2_2 V4 = { - "checksum_support": True, - "objects": { + 'checksum_support': True, + 'objects': { obis.P1_MESSAGE_HEADER: CosemParser(ValueParser(str)), obis.P1_MESSAGE_TIMESTAMP: CosemParser(ValueParser(timestamp)), obis.EQUIPMENT_IDENTIFIER: CosemParser(ValueParser(str)), @@ -70,9 +61,10 @@ V4 = { obis.CURRENT_ELECTRICITY_DELIVERY: CosemParser(ValueParser(Decimal)), obis.SHORT_POWER_FAILURE_COUNT: CosemParser(ValueParser(int)), obis.LONG_POWER_FAILURE_COUNT: CosemParser(ValueParser(int)), - obis.POWER_EVENT_FAILURE_LOG: ProfileGenericParser( - BUFFER_TYPES, PG_HEAD_PARSERS, PG_UNIDENTIFIED_BUFFERTYPE_PARSERS - ), + obis.POWER_EVENT_FAILURE_LOG: + ProfileGenericParser(BUFFER_TYPES, + PG_HEAD_PARSERS, + PG_UNIDENTIFIED_BUFFERTYPE_PARSERS), obis.VOLTAGE_SAG_L1_COUNT: CosemParser(ValueParser(int)), obis.VOLTAGE_SAG_L2_COUNT: CosemParser(ValueParser(int)), obis.VOLTAGE_SAG_L3_COUNT: CosemParser(ValueParser(int)), @@ -93,14 +85,15 @@ V4 = { obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE: CosemParser(ValueParser(Decimal)), obis.EQUIPMENT_IDENTIFIER_GAS: CosemParser(ValueParser(str)), obis.HOURLY_GAS_METER_READING: MBusParser( - ValueParser(timestamp), ValueParser(Decimal) - ), - }, + ValueParser(timestamp), + ValueParser(Decimal) + ) + } } V5 = { - "checksum_support": True, - "objects": { + 'checksum_support': True, + 'objects': { obis.P1_MESSAGE_HEADER: CosemParser(ValueParser(str)), obis.P1_MESSAGE_TIMESTAMP: CosemParser(ValueParser(timestamp)), obis.EQUIPMENT_IDENTIFIER: CosemParser(ValueParser(str)), @@ -114,9 +107,10 @@ V5 = { obis.CURRENT_ELECTRICITY_DELIVERY: CosemParser(ValueParser(Decimal)), obis.LONG_POWER_FAILURE_COUNT: CosemParser(ValueParser(int)), obis.SHORT_POWER_FAILURE_COUNT: CosemParser(ValueParser(int)), - obis.POWER_EVENT_FAILURE_LOG: ProfileGenericParser( - BUFFER_TYPES, PG_HEAD_PARSERS, PG_UNIDENTIFIED_BUFFERTYPE_PARSERS - ), + obis.POWER_EVENT_FAILURE_LOG: + ProfileGenericParser(BUFFER_TYPES, + PG_HEAD_PARSERS, + PG_UNIDENTIFIED_BUFFERTYPE_PARSERS), obis.VOLTAGE_SAG_L1_COUNT: CosemParser(ValueParser(int)), obis.VOLTAGE_SAG_L2_COUNT: CosemParser(ValueParser(int)), obis.VOLTAGE_SAG_L3_COUNT: CosemParser(ValueParser(int)), @@ -139,46 +133,38 @@ V5 = { obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE: CosemParser(ValueParser(Decimal)), obis.EQUIPMENT_IDENTIFIER_GAS: CosemParser(ValueParser(str)), obis.HOURLY_GAS_METER_READING: MBusParser( - ValueParser(timestamp), ValueParser(Decimal) - ), - }, + ValueParser(timestamp), + ValueParser(Decimal) + ) + } } ALL = (V2_2, V3, V4, V5) BELGIUM_FLUVIUS = deepcopy(V5) -BELGIUM_FLUVIUS["objects"].update( - { - obis.BELGIUM_HOURLY_GAS_METER_READING: MBusParser( - ValueParser(timestamp), ValueParser(Decimal) - ) - } -) +BELGIUM_FLUVIUS['objects'].update({ + obis.BELGIUM_HOURLY_GAS_METER_READING: MBusParser( + ValueParser(timestamp), + ValueParser(Decimal) + ) +}) LUXEMBOURG_SMARTY = deepcopy(V5) -LUXEMBOURG_SMARTY["objects"].update( - { - obis.LUXEMBOURG_EQUIPMENT_IDENTIFIER: CosemParser(ValueParser(str)), - obis.LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL: CosemParser( - ValueParser(Decimal) - ), - obis.LUXEMBOURG_ELECTRICITY_DELIVERED_TARIFF_GLOBAL: CosemParser( - ValueParser(Decimal) - ), - } -) +LUXEMBOURG_SMARTY['objects'].update({ + obis.LUXEMBOURG_EQUIPMENT_IDENTIFIER: CosemParser(ValueParser(str)), + obis.LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL: CosemParser(ValueParser(Decimal)), + obis.LUXEMBOURG_ELECTRICITY_DELIVERED_TARIFF_GLOBAL: CosemParser(ValueParser(Decimal)), +}) # Source: https://www.energiforetagen.se/globalassets/energiforetagen/det-erbjuder-vi/kurser-och-konferenser/elnat/branschrekommendation-lokalt-granssnitt-v2_0-201912.pdf SWEDEN = { - "checksum_support": True, - "objects": { + 'checksum_support': True, + 'objects': { obis.P1_MESSAGE_HEADER: CosemParser(ValueParser(str)), obis.P1_MESSAGE_TIMESTAMP: CosemParser(ValueParser(timestamp)), obis.SWEDEN_ELECTRICITY_USED_TARIFF_GLOBAL: CosemParser(ValueParser(Decimal)), - obis.SWEDEN_ELECTRICITY_DELIVERED_TARIFF_GLOBAL: CosemParser( - ValueParser(Decimal) - ), + obis.SWEDEN_ELECTRICITY_DELIVERED_TARIFF_GLOBAL: CosemParser(ValueParser(Decimal)), obis.CURRENT_ELECTRICITY_USAGE: CosemParser(ValueParser(Decimal)), obis.CURRENT_ELECTRICITY_DELIVERY: CosemParser(ValueParser(Decimal)), obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE: CosemParser(ValueParser(Decimal)), @@ -193,7 +179,7 @@ SWEDEN = { obis.INSTANTANEOUS_CURRENT_L1: CosemParser(ValueParser(Decimal)), obis.INSTANTANEOUS_CURRENT_L2: CosemParser(ValueParser(Decimal)), obis.INSTANTANEOUS_CURRENT_L3: CosemParser(ValueParser(Decimal)), - }, + } } Q3D = {