Compare commits

...
31 Commits
Author SHA1 Message Date
Nigel c04b0a5add Updated version number 2019-03-04 20:31:51 +01:00
Nigel Dokter ed2290a597 Merge pull request #33 from mleenaerts/patch-1
Fix DSMR v5.0 serial settings which were not used
2019-01-22 19:27:56 +01:00
Mark Leenaerts 85c67464a1 Fix DSMR v5.0 serial settings which were not used
While analysing some CRC check errors I encounter within the home-assistant plugin (which uses this component) I encountered this oversight in the code.
2019-01-19 16:11:12 +01:00
Nigel Dokter 48783acc00 Update CHANGELOG.rst 2018-09-23 13:01:22 +02:00
Nigel Dokter 41f6a7ac16 Update CHANGELOG.rst 2018-09-23 13:01:04 +02:00
Nigel Dokter 59811dbf9f Update setup.py 2018-09-23 12:59:02 +02:00
Nigel Dokter 9b09969763 Merge pull request #31 from tneele/master
Add serial settings for DSMR v5.0
2018-09-23 12:50:01 +02:00
Nigel Dokter 64f5dc2e87 Merge pull request #32 from bossjl/master
Lux-creos-obis-1.8.0
2018-09-23 12:49:42 +02:00
bossjl 887dd3a2aa Lux-creos-obis-1.8.0 2018-09-21 18:37:32 +02:00
Thomas Neele ad6ab304f5 Added serial settings for DSMR v5.0 2018-09-15 21:23:22 +02:00
Nigel Dokter 8582395017 Merge pull request #30 from jk-5/sagemcom-t210-d
Added missing values for 3-phase sagemcom TD210-D meter
2018-09-12 23:45:29 +02:00
jk-5 3327c78c0e Updated unittests 2018-09-06 15:49:11 +02:00
jk-5 472c54968e Corrected meter types 2018-09-06 15:40:02 +02:00
jk-5 d534b1d8b0 Added missing values for 3-phase sagemcom TD210-D meter 2018-09-06 14:53:30 +02:00
Nigel Dokter d94bc8de03 updated version 2017-09-18 12:02:36 +02:00
Nigel Dokter 41381f1705 Merge pull request #26 from vavdb/patch-1
Optional NUL after checksum
2017-09-18 11:55:31 +02:00
Vincent van den Braken e3203a5334 Optional NUL after checksum
My smart meter returns 00 0D 0A after the checksum, not just 0D 0A.
2017-09-15 13:48:10 +02:00
Nigel Dokter c78ebe3e2d fixed import errors 2017-06-05 21:06:48 +02:00
Nigel Dokter d6e28db116 log checksum errors as warning; dont force full telegram signatures; removed unused code for automatic telegram version detection; 2017-06-05 21:02:59 +02:00
Nigel Dokter 5f1afeb1f8 Merge pull request #25 from AlexMekkering/optional_telegram_lines
Support optional telegram signatures
2017-06-05 20:45:38 +02:00
Alex Mekkering dcb59fddb1 Support optional telegram signatures 2017-06-05 09:07:47 +02:00
Nigel Dokter 9b0a85e84b updated version 2017-05-12 21:37:54 +02:00
Nigel Dokter 1dca6ab396 Merge pull request #23 from aequitas/dsmr5
Add DSMR5 option to protocol.
2017-05-12 21:34:06 +02:00
Johan Bloemberg efc09df71f Add DSMR5 option to protocol. 2017-05-12 20:30:53 +02:00
Nigel Dokter de5c884d8d Small comment improvement 2017-02-27 20:44:18 +01:00
Nigel Dokter d2f57a8926 fixed pep8 2017-02-27 20:35:19 +01:00
Nigel Dokter 3d64fea247 Updated README 2017-02-27 20:26:15 +01:00
Nigel Dokter 46860e04c1 Formatting 2017-02-03 22:42:31 +01:00
Nigel Dokter 148bdabc12 Updated docs 2017-02-03 22:40:39 +01:00
Nigel Dokter 9d20bb8ad5 experimenting with version detection 2017-01-28 17:01:33 +01:00
Nigel Dokter 24ab9aa712 experimenting with version detection 2017-01-28 17:01:02 +01:00
13 changed files with 230 additions and 66 deletions
+23
View File
@@ -1,6 +1,29 @@
Change Log
----------
**0.13** (2019-03-04)
- Fix DSMR v5.0 serial settings which were not used (`pull request #33 <https://github.com/ndokter/dsmr_parser/pull/33>`_).
**0.12** (2018-09-23)
- Add serial settings for DSMR v5.0 (`pull request #31 <https://github.com/ndokter/dsmr_parser/pull/31>`_).
- Lux-creos-obis-1.8.0 (`pull request #32 <https://github.com/ndokter/dsmr_parser/pull/32>`_).
**0.11** (2017-09-18)
- NULL value fix in checksum (`pull request #26 <https://github.com/ndokter/dsmr_parser/pull/26>`_)
**0.10** (2017-06-05)
- bugix: don't force full telegram signatures (`pull request #25 <https://github.com/ndokter/dsmr_parser/pull/25>`_)
- removed unused code for automatic telegram detection as this needs reworking after the fix mentioned above
- InvalidChecksumError's are logged as warning instead of error
**0.9** (2017-05-12)
- added DSMR v5 serial settings
**0.8** (2017-01-26)
- added support for DSMR v3
+111 -26
View File
@@ -8,7 +8,7 @@ DSMR Parser
:target: https://travis-ci.org/ndokter/dsmr_parser
A library for parsing Dutch Smart Meter Requirements (DSMR) telegram data. It
also includes a serial client to directly read and parse smart meter data.
also includes client implementation to directly read and parse smart meter data.
Features
@@ -17,41 +17,126 @@ Features
DSMR Parser supports DSMR versions 2, 3, 4 and 5. It has been tested with Python 3.4, 3.5 and 3.6.
Examples
--------
Client module usage
-------------------
Using the serial reader to connect to your smart meter and parse it's telegrams:
**Serial client**
Read the serial port and work with the parsed telegrams. It should be run in a separate
process because the code is blocking (not asynchronous):
.. code-block:: python
from dsmr_parser import telegram_specifications
from dsmr_parser.clients import SerialReader, SERIAL_SETTINGS_V4
serial_reader = SerialReader(
device='/dev/ttyUSB0',
serial_settings=SERIAL_SETTINGS_V4,
telegram_specification=telegram_specifications.V4
)
for telegram in serial_reader.read():
print(telegram) # see 'Telegram object' docs below
**AsyncIO client**
To be documented.
Parsing module usage
--------------------
The parsing module accepts complete unaltered telegram strings and parses these
into a dictionary.
.. code-block:: python
from dsmr_parser import telegram_specifications
from dsmr_parser.parsers import TelegramParser
# String is formatted in separate lines for readability.
telegram_str = (
'/ISk5\2MT382-1000\r\n'
'\r\n'
'0-0:96.1.1(4B384547303034303436333935353037)\r\n'
'1-0:1.8.1(12345.678*kWh)\r\n'
'1-0:1.8.2(12345.678*kWh)\r\n'
'1-0:2.8.1(12345.678*kWh)\r\n'
'1-0:2.8.2(12345.678*kWh)\r\n'
'0-0:96.14.0(0002)\r\n'
'1-0:1.7.0(001.19*kW)\r\n'
'1-0:2.7.0(000.00*kW)\r\n'
'0-0:17.0.0(016*A)\r\n'
'0-0:96.3.10(1)\r\n'
'0-0:96.13.1(303132333435363738)\r\n'
'0-0:96.13.0(303132333435363738393A3B3C3D3E3F303132333435363738393A3B3C3D3E'
'3F303132333435363738393A3B3C3D3E3F303132333435363738393A3B3C3D3E3F30313233'
'3435363738393A3B3C3D3E3F)\r\n'
'0-1:96.1.0(3232323241424344313233343536373839)\r\n'
'0-1:24.1.0(03)\r\n'
'0-1:24.3.0(090212160000)(00)(60)(1)(0-1:24.2.1)(m3)\r\n'
'(00001.001)\r\n'
'0-1:24.4.0(1)\r\n'
'!\r\n'
)
parser = TelegramParser(telegram_specifications.V3)
telegram = parser.parse(telegram_str)
print(telegram) # see 'Telegram object' docs below
Telegram object
---------------
A dictionary of which the key indicates the field type. These regex values
correspond to one of dsmr_parser.obis_reference constants.
The value is either a CosemObject or MBusObject. These have a 'value' and 'unit'
property. MBusObject's additionally have a 'datetime' property. The 'value' can
contain any python type (int, str, Decimal) depending on the field. The 'unit'
contains 'kW', 'A', 'kWh' or 'm3'.
.. code-block:: python
# Contents of a parsed DSMR v3 telegram
{'\\d-\\d:17\\.0\\.0.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fc39eb8>,
'\\d-\\d:1\\.7\\.0.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10f916390>,
'\\d-\\d:1\\.8\\.1.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fc39e10>,
'\\d-\\d:1\\.8\\.2.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fc39ef0>,
'\\d-\\d:24\\.1\\.0.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fbaef28>,
'\\d-\\d:24\\.3\\.0.+?\\r\\n.+?\\r\\n': <dsmr_parser.objects.MBusObject object at 0x10f9163c8>,
'\\d-\\d:24\\.4\\.0.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fc39f60>,
'\\d-\\d:2\\.7\\.0.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fc39fd0>,
'\\d-\\d:2\\.8\\.1.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fbaee10>,
'\\d-\\d:2\\.8\\.2.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fc39e80>,
'\\d-\\d:96\\.13\\.0.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fc39d30>,
'\\d-\\d:96\\.13\\.1.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fbaeeb8>,
'\\d-\\d:96\\.14\\.0.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fbaef98>,
'\\d-\\d:96\\.1\\.0.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fbaef60>,
'\\d-\\d:96\\.1\\.1.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fc39f98>,
'\\d-\\d:96\\.3\\.10.+?\\r\\n': <dsmr_parser.objects.CosemObject object at 0x10fc39dd8>}
Example to get some of the values:
.. code-block:: python
from dsmr_parser import telegram_specifications
from dsmr_parser import obis_references
from dsmr_parser.clients import SerialReader, SERIAL_SETTINGS_V4
serial_reader = SerialReader(
device='/dev/ttyUSB0',
serial_settings=SERIAL_SETTINGS_V4,
telegram_specification=telegram_specifications.V4
)
# The telegram message timestamp.
message_datetime = telegram[obis_references.P1_MESSAGE_TIMESTAMP]
for telegram in serial_reader.read():
# Using the active tariff to determine the electricity being used and
# delivered for the right tariff.
active_tariff = telegram[obis_references.ELECTRICITY_ACTIVE_TARIFF]
active_tariff = int(tariff.value)
# The telegram message timestamp.
message_datetime = telegram[obis_references.P1_MESSAGE_TIMESTAMP]
electricity_used_total = telegram[obis_references.ELECTRICITY_USED_TARIFF_ALL[active_tariff - 1]]
electricity_delivered_total = telegram[obis_references.ELECTRICITY_DELIVERED_TARIFF_ALL[active_tariff - 1]]
# Using the active tariff to determine the electricity being used and
# delivered for the right tariff.
tariff = telegram[obis_references.ELECTRICITY_ACTIVE_TARIFF]
tariff = int(tariff.value)
gas_reading = telegram[obis_references.HOURLY_GAS_METER_READING]
electricity_used_total \
= telegram[obis_references.ELECTRICITY_USED_TARIFF_ALL[tariff - 1]]
electricity_delivered_total = \
telegram[obis_referencesELECTRICITY_DELIVERED_TARIFF_ALL[tariff - 1]]
gas_reading = telegram[obis_references.HOURLY_GAS_METER_READING]
# See dsmr_reader.obis_references for all readable telegram values.
# See dsmr_reader.obis_references for all readable telegram values.
# Note that the avilable values differ per DSMR version.
Installation
+1 -1
View File
@@ -1,5 +1,5 @@
from dsmr_parser.clients.settings import SERIAL_SETTINGS_V2_2, \
SERIAL_SETTINGS_V4
SERIAL_SETTINGS_V4, SERIAL_SETTINGS_V5
from dsmr_parser.clients.serial_ import SerialReader, AsyncSerialReader
from dsmr_parser.clients.protocol import create_dsmr_protocol, \
create_dsmr_reader, create_tcp_dsmr_reader
+7 -2
View File
@@ -8,10 +8,10 @@ from serial_asyncio import create_serial_connection
from dsmr_parser import telegram_specifications
from dsmr_parser.clients.telegram_buffer import TelegramBuffer
from dsmr_parser.exceptions import ParseError
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_V4, SERIAL_SETTINGS_V5
def create_dsmr_protocol(dsmr_version, telegram_callback, loop=None):
@@ -23,6 +23,9 @@ def create_dsmr_protocol(dsmr_version, telegram_callback, loop=None):
elif dsmr_version == '4':
specification = telegram_specifications.V4
serial_settings = SERIAL_SETTINGS_V4
elif dsmr_version == '5':
specification = telegram_specifications.V5
serial_settings = SERIAL_SETTINGS_V5
else:
raise NotImplementedError("No telegram parser found for version: %s",
dsmr_version)
@@ -98,6 +101,8 @@ class DSMRProtocol(asyncio.Protocol):
try:
parsed_telegram = self.telegram_parser.parse(telegram)
except InvalidChecksumError as e:
self.log.warning(str(e))
except ParseError:
self.log.exception("failed to parse telegram")
else:
+3 -1
View File
@@ -4,7 +4,7 @@ import serial
import serial_asyncio
from dsmr_parser.clients.telegram_buffer import TelegramBuffer
from dsmr_parser.exceptions import ParseError
from dsmr_parser.exceptions import ParseError, InvalidChecksumError
from dsmr_parser.parsers import TelegramParser
@@ -36,6 +36,8 @@ class SerialReader(object):
for telegram in self.telegram_buffer.get_all():
try:
yield self.telegram_parser.parse(telegram)
except InvalidChecksumError as e:
logger.warning(str(e))
except ParseError as e:
logger.error('Failed to parse telegram: %s', e)
+10
View File
@@ -20,3 +20,13 @@ SERIAL_SETTINGS_V4 = {
'rtscts': 0,
'timeout': 20
}
SERIAL_SETTINGS_V5 = {
'baudrate': 115200,
'bytesize': serial.EIGHTBITS,
'parity': serial.PARITY_NONE,
'stopbits': serial.STOPBITS_ONE,
'xonxoff': 0,
'rtscts': 0,
'timeout': 20
}
+1 -1
View File
@@ -51,7 +51,7 @@ class TelegramBuffer(object):
# - The checksum is optional '{0,4}' because not all telegram versions
# support it.
return re.findall(
r'\/[^\/]+?\![A-F0-9]{0,4}\r\n',
r'\/[^\/]+?\![A-F0-9]{0,4}\0?\r\n',
self._buffer,
re.DOTALL
)
+8
View File
@@ -8,6 +8,7 @@ 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_DELIVERED_TARIFF_1 = r'\d-\d:2\.8\.1.+?\r\n'
@@ -17,6 +18,7 @@ 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'
@@ -24,6 +26,12 @@ 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'
+3
View File
@@ -1,4 +1,7 @@
class DSMRObject(object):
"""
Represents all data from a single telegram line.
"""
def __init__(self, values):
self.values = values
+8 -5
View File
@@ -27,8 +27,8 @@ class TelegramParser(object):
The telegram str type makes python 2.x integration easier.
:param str telegram: full telegram from start ('/') to checksum
('!ABCD') including line endings inbetween the telegram's lines
:param str telegram_data: full telegram from start ('/') to checksum
('!ABCD') including line endings in between the telegram's lines
:rtype: dict
:returns: Shortened example:
{
@@ -51,6 +51,8 @@ class TelegramParser(object):
for signature, parser in self.telegram_specification['objects'].items():
match = re.search(signature, telegram_data, re.DOTALL)
# Some signatures are optional and may not be present,
# so only parse lines that match
if match:
telegram[signature] = parser.parse(match.group(0))
@@ -147,10 +149,11 @@ class CosemParser(DSMRObjectParser):
1 23 45
1) OBIS Reduced ID-code
2) Separator “(“, ASCII 28h
2) Separator "(", ASCII 28h
3) COSEM object attribute value
4) Unit of measurement values (Unit of capture objects attribute) – only if applicable
5) Separator “)”, ASCII 29h
4) Unit of measurement values (Unit of capture objects attribute) - only if
applicable
5) Separator ")", ASCII 29h
"""
def parse(self, line):
+11 -28
View File
@@ -42,34 +42,7 @@ V2_2 = {
}
}
V3 = {
'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)),
obis.ELECTRICITY_DELIVERED_TARIFF_1: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_DELIVERED_TARIFF_2: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_ACTIVE_TARIFF: CosemParser(ValueParser(str)),
obis.CURRENT_ELECTRICITY_USAGE: CosemParser(ValueParser(Decimal)),
obis.CURRENT_ELECTRICITY_DELIVERY: CosemParser(ValueParser(Decimal)),
obis.ACTUAL_TRESHOLD_ELECTRICITY: CosemParser(ValueParser(Decimal)),
obis.ACTUAL_SWITCH_POSITION: CosemParser(ValueParser(str)),
obis.TEXT_MESSAGE_CODE: CosemParser(ValueParser(int)),
obis.TEXT_MESSAGE: CosemParser(ValueParser(str)),
obis.EQUIPMENT_IDENTIFIER_GAS: CosemParser(ValueParser(str)),
obis.DEVICE_TYPE: CosemParser(ValueParser(str)),
obis.VALVE_POSITION_GAS: CosemParser(ValueParser(str)),
obis.GAS_METER_READING: MBusParser(
ValueParser(timestamp),
ValueParser(int),
ValueParser(int),
ValueParser(int),
ValueParser(str),
ValueParser(Decimal),
),
}
}
V3 = V2_2
V4 = {
'checksum_support': True,
@@ -115,6 +88,7 @@ V5 = {
obis.P1_MESSAGE_HEADER: CosemParser(ValueParser(str)),
obis.P1_MESSAGE_TIMESTAMP: CosemParser(ValueParser(timestamp)),
obis.EQUIPMENT_IDENTIFIER: CosemParser(ValueParser(str)),
obis.ELECTRICITY_IMPORTED_TOTAL: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_USED_TARIFF_1: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_USED_TARIFF_2: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_DELIVERED_TARIFF_1: CosemParser(ValueParser(Decimal)),
@@ -123,6 +97,7 @@ V5 = {
obis.CURRENT_ELECTRICITY_USAGE: CosemParser(ValueParser(Decimal)),
obis.CURRENT_ELECTRICITY_DELIVERY: CosemParser(ValueParser(Decimal)),
obis.LONG_POWER_FAILURE_COUNT: CosemParser(ValueParser(int)),
obis.SHORT_POWER_FAILURE_COUNT: CosemParser(ValueParser(int)),
# POWER_EVENT_FAILURE_LOG: ProfileGenericParser(), TODO
obis.VOLTAGE_SAG_L1_COUNT: CosemParser(ValueParser(int)),
obis.VOLTAGE_SAG_L2_COUNT: CosemParser(ValueParser(int)),
@@ -130,6 +105,12 @@ V5 = {
obis.VOLTAGE_SWELL_L1_COUNT: CosemParser(ValueParser(int)),
obis.VOLTAGE_SWELL_L2_COUNT: CosemParser(ValueParser(int)),
obis.VOLTAGE_SWELL_L3_COUNT: CosemParser(ValueParser(int)),
obis.INSTANTANEOUS_VOLTAGE_L1: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_VOLTAGE_L2: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_VOLTAGE_L3: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_CURRENT_L1: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_CURRENT_L2: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_CURRENT_L3: CosemParser(ValueParser(Decimal)),
obis.TEXT_MESSAGE: CosemParser(ValueParser(str)),
obis.DEVICE_TYPE: CosemParser(ValueParser(int)),
obis.INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE: CosemParser(ValueParser(Decimal)),
@@ -145,3 +126,5 @@ V5 = {
)
}
}
ALL = (V2_2, V3, V4, V5)
+2 -2
View File
@@ -4,9 +4,9 @@ setup(
name='dsmr-parser',
description='Library to parse Dutch Smart Meter Requirements (DSMR)',
author='Nigel Dokter',
author_email='nigeldokter@gmail.com',
author_email='nigel@nldr.net',
url='https://github.com/ndokter/dsmr_parser',
version='0.8',
version='0.13',
packages=find_packages(),
install_requires=[
'pyserial>=3,<4',
+42
View File
@@ -87,6 +87,12 @@ class TelegramParserV5Test(unittest.TestCase):
assert isinstance(result[obis.LONG_POWER_FAILURE_COUNT].value, int)
assert result[obis.LONG_POWER_FAILURE_COUNT].value == 0
# SHORT_POWER_FAILURE_COUNT (1-0:96.7.21)
assert isinstance(result[obis.SHORT_POWER_FAILURE_COUNT], CosemObject)
assert result[obis.SHORT_POWER_FAILURE_COUNT].unit is None
assert isinstance(result[obis.SHORT_POWER_FAILURE_COUNT].value, int)
assert result[obis.SHORT_POWER_FAILURE_COUNT].value == 13
# VOLTAGE_SAG_L1_COUNT (1-0:32.32.0)
assert isinstance(result[obis.VOLTAGE_SAG_L1_COUNT], CosemObject)
assert result[obis.VOLTAGE_SAG_L1_COUNT].unit is None
@@ -123,6 +129,42 @@ class TelegramParserV5Test(unittest.TestCase):
assert isinstance(result[obis.VOLTAGE_SWELL_L3_COUNT].value, int)
assert result[obis.VOLTAGE_SWELL_L3_COUNT].value == 0
# INSTANTANEOUS_VOLTAGE_L1 (1-0:32.7.0)
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L1], CosemObject)
assert result[obis.INSTANTANEOUS_VOLTAGE_L1].unit == 'V'
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L1].value, Decimal)
assert result[obis.INSTANTANEOUS_VOLTAGE_L1].value == Decimal('230.0')
# INSTANTANEOUS_VOLTAGE_L2 (1-0:52.7.0)
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L2], CosemObject)
assert result[obis.INSTANTANEOUS_VOLTAGE_L2].unit == 'V'
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L2].value, Decimal)
assert result[obis.INSTANTANEOUS_VOLTAGE_L2].value == Decimal('230.0')
# INSTANTANEOUS_VOLTAGE_L3 (1-0:72.7.0)
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L3], CosemObject)
assert result[obis.INSTANTANEOUS_VOLTAGE_L3].unit == 'V'
assert isinstance(result[obis.INSTANTANEOUS_VOLTAGE_L3].value, Decimal)
assert result[obis.INSTANTANEOUS_VOLTAGE_L3].value == Decimal('229.0')
# INSTANTANEOUS_CURRENT_L1 (1-0:31.7.0)
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L1], CosemObject)
assert result[obis.INSTANTANEOUS_CURRENT_L1].unit == 'A'
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L1].value, Decimal)
assert result[obis.INSTANTANEOUS_CURRENT_L1].value == Decimal('0.48')
# INSTANTANEOUS_CURRENT_L2 (1-0:51.7.0)
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L2], CosemObject)
assert result[obis.INSTANTANEOUS_CURRENT_L2].unit == 'A'
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L2].value, Decimal)
assert result[obis.INSTANTANEOUS_CURRENT_L2].value == Decimal('0.44')
# INSTANTANEOUS_CURRENT_L3 (1-0:71.7.0)
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L3], CosemObject)
assert result[obis.INSTANTANEOUS_CURRENT_L3].unit == 'A'
assert isinstance(result[obis.INSTANTANEOUS_CURRENT_L3].value, Decimal)
assert result[obis.INSTANTANEOUS_CURRENT_L3].value == Decimal('0.86')
# TEXT_MESSAGE (0-0:96.13.0)
assert isinstance(result[obis.TEXT_MESSAGE], CosemObject)
assert result[obis.TEXT_MESSAGE].unit is None