Compare commits

...
18 Commits
Author SHA1 Message Date
Nigel ca8392504d Release 1.1.0 2023-02-08 12:02:14 +01:00
Nigel 026b91cd49 Merge pull request #124 from yada75/reactive
add instantaneous reactive power + fixed swapped reactive total import export
2023-01-28 13:32:32 +01:00
yada75 02eb3a34dd Update obis_name_mapping.py 2023-01-18 20:02:54 +01:00
yada75 142b7359a1 Update telegram_specifications.py 2023-01-18 19:39:29 +01:00
yada75 21b8547655 Update obis_name_mapping.py 2023-01-18 19:34:35 +01:00
yada75 a2b9fe5e3b Update obis_references.py 2023-01-18 19:31:39 +01:00
Nigel 0a259a3c9d fix code style 2023-01-01 20:55:58 +01:00
Nigel f851f48225 Merge pull request #118 from dennissiemensma/bug/readme-shield
Fixed Shields badge in favor of badges/shields#8671
2023-01-01 20:37:24 +01:00
Nigel 3a3054324a Merge pull request #116 from lowdef/add_pylama_backin_post_py36
add pylama back in + fix uniform style issues reported by pylama
2023-01-01 20:36:39 +01:00
Nigel 041ac758f4 Merge pull request #115 from robcalon/patch-1
asynchronous read_as_object method
2023-01-01 20:35:48 +01:00
Dennis Siemensma d50d775e38 Fixed Shields badge in favor of badges/shields#8671 2022-12-30 21:05:17 +01:00
Nigel 10613acbd9 Merge pull request #114 from dupondje/fix_name_mapping
Fix missing value from name mapping
2022-12-29 19:50:26 +01:00
Hans Erik van Elburg 5f58bc8f72 add pylama back in + fix uniform style issues reported by pylama 2022-12-27 18:58:48 +01:00
Rob Calon 371e1f3c5e update docstring 2022-12-27 17:36:10 +01:00
Rob Calon 0eae28e183 correct rtype 2022-12-27 17:27:23 +01:00
Rob Calon 431ddadb5f asynchronous read_as_object method
fix inheritance of synchronous read_as_object method from parent
2022-12-27 17:20:24 +01:00
Jean-Louis Dupond 9e01dc32c0 Fix missing value from name mapping 2022-12-26 12:50:59 +01:00
Nigel 650d16862b Fix changelog 2022-12-22 10:18:47 +01:00
11 changed files with 91 additions and 12 deletions
+6 -1
View File
@@ -1,10 +1,15 @@
Change Log
----------
**1.1.0** (2023-02-08)
- Add instantaneous reactive power + fixed swapped reactive total import export (`pull request #124 <https://github.com/ndokter/dsmr_parser/pull/124>`_ by `yada75 <https://github.com/yada75>`_)
**1.0.0** (2022-12-22)
- switched to new numbering scheme https://semver.org/
- Added support for Python 3.11 and dropped support for Python 3.6 (`pull request #110 <https://github.com/ndokter/dsmr_parser/pull/112>`_)
- Added support for Python 3.11 and dropped support for Python 3.6 (`pull request #112 <https://github.com/ndokter/dsmr_parser/pull/112>`_)
- Add support for Fluvius V1.7.1 DSMR messages (`pull request #110 <https://github.com/ndokter/dsmr_parser/pull/113>`_)
**0.34** (2022-10-19)
+1 -1
View File
@@ -4,7 +4,7 @@ DSMR Parser
.. image:: https://img.shields.io/pypi/v/dsmr-parser.svg
:target: https://pypi.python.org/pypi/dsmr-parser
.. image:: https://img.shields.io/github/workflow/status/ndokter/dsmr_parser/Tests/master
.. image:: https://img.shields.io/github/actions/workflow/status/ndokter/dsmr_parser/tests.yml?branch=master
:target: https://github.com/ndokter/dsmr_parser/actions/workflows/tests.yml
A library for parsing Dutch Smart Meter Requirements (DSMR) telegram data. It
+32
View File
@@ -95,3 +95,35 @@ class AsyncSerialReader(SerialReader):
)
except ParseError as e:
logger.warning('Failed to parse telegram: %s', e)
async def read_as_object(self, queue):
"""
Read complete DSMR telegram's from the serial interface
and return a Telegram object.
Instead of being a generator, Telegram objects are pushed
to provided queue for asynchronous processing.
:rtype: None
"""
# create Serial StreamReader
conn = serial_asyncio.open_serial_connection(**self.serial_settings)
reader, _ = await conn
while True:
# Read line if available or give control back to loop until new
# data has arrived.
data = await reader.readline()
self.telegram_buffer.append(data.decode('ascii'))
for telegram in self.telegram_buffer.get_all():
try:
queue.put_nowait(
Telegram(telegram, self.telegram_parser, self.telegram_specification)
)
except InvalidChecksumError as e:
logger.warning(str(e))
except ParseError as e:
logger.error('Failed to parse telegram: %s', e)
+9
View File
@@ -11,9 +11,11 @@ EN = {
obis.P1_MESSAGE_HEADER: 'P1_MESSAGE_HEADER',
obis.P1_MESSAGE_TIMESTAMP: 'P1_MESSAGE_TIMESTAMP',
obis.ELECTRICITY_IMPORTED_TOTAL: 'ELECTRICITY_IMPORTED_TOTAL',
obis.ELECTRICITY_REACTIVE_IMPORTED_TOTAL: 'ELECTRICITY_REACTIVE_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_REACTIVE_EXPORTED_TOTAL: 'ELECTRICITY_REACTIVE_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',
@@ -44,12 +46,19 @@ EN = {
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.INSTANTANEOUS_REACTIVE_POWER_L1_POSITIVE: 'INSTANTANEOUS_REACTIVE_POWER_L1_POSITIVE',
obis.INSTANTANEOUS_REACTIVE_POWER_L1_NEGATIVE: 'INSTANTANEOUS_REACTIVE_POWER_L1_NEGATIVE',
obis.INSTANTANEOUS_REACTIVE_POWER_L2_POSITIVE: 'INSTANTANEOUS_REACTIVE_POWER_L2_POSITIVE',
obis.INSTANTANEOUS_REACTIVE_POWER_L2_NEGATIVE: 'INSTANTANEOUS_REACTIVE_POWER_L2_NEGATIVE',
obis.INSTANTANEOUS_REACTIVE_POWER_L3_POSITIVE: 'INSTANTANEOUS_REACTIVE_POWER_L3_POSITIVE',
obis.INSTANTANEOUS_REACTIVE_POWER_L3_NEGATIVE: 'INSTANTANEOUS_REACTIVE_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_VERSION_INFORMATION: 'BELGIUM_VERSION_INFORMATION',
obis.BELGIUM_EQUIPMENT_IDENTIFIER: 'BELGIUM_EQUIPMENT_IDENTIFIER',
obis.BELGIUM_CURRENT_AVERAGE_DEMAND: 'BELGIUM_CURRENT_AVERAGE_DEMAND',
obis.BELGIUM_MAXIMUM_DEMAND_MONTH: 'BELGIUM_MAXIMUM_DEMAND_MONTH',
+8 -2
View File
@@ -12,11 +12,11 @@ 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'
ELECTRICITY_DELIVERED_TARIFF_2 = r'\d-\d:2\.8\.2.+?\r\n'
CURRENT_REACTIVE_EXPORTED = r'\d-\d:3\.7\.0.+?\r\n'
CURRENT_REACTIVE_IMPORTED = r'\d-\d:3\.7\.0.+?\r\n'
ELECTRICITY_REACTIVE_IMPORTED_TOTAL = r'\d-\d:3\.8\.0.+?\r\n'
ELECTRICITY_REACTIVE_IMPORTED_TARIFF_1 = r'\d-\d:3\.8\.1.+?\r\n'
ELECTRICITY_REACTIVE_IMPORTED_TARIFF_2 = r'\d-\d:3\.8\.2.+?\r\n'
CURRENT_REACTIVE_IMPORTED = r'\d-\d:4\.7\.0.+?\r\n'
CURRENT_REACTIVE_EXPORTED = r'\d-\d:4\.7\.0.+?\r\n'
ELECTRICITY_REACTIVE_EXPORTED_TOTAL = r'\d-\d:4\.8\.0.+?\r\n'
ELECTRICITY_REACTIVE_EXPORTED_TARIFF_1 = r'\d-\d:4\.8\.1.+?\r\n'
ELECTRICITY_REACTIVE_EXPORTED_TARIFF_2 = r'\d-\d:4\.8\.2.+?\r\n'
@@ -48,6 +48,12 @@ 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'
INSTANTANEOUS_REACTIVE_POWER_L1_POSITIVE = r'\d-\d:23\.7\.0.+?\r\n'
INSTANTANEOUS_REACTIVE_POWER_L1_NEGATIVE = r'\d-\d:24\.7\.0.+?\r\n'
INSTANTANEOUS_REACTIVE_POWER_L2_POSITIVE = r'\d-\d:43\.7\.0.+?\r\n'
INSTANTANEOUS_REACTIVE_POWER_L2_NEGATIVE = r'\d-\d:44\.7\.0.+?\r\n'
INSTANTANEOUS_REACTIVE_POWER_L3_POSITIVE = r'\d-\d:63\.7\.0.+?\r\n'
INSTANTANEOUS_REACTIVE_POWER_L3_NEGATIVE = r'\d-\d:64\.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'
+4 -1
View File
@@ -113,6 +113,7 @@ class MBusObject(DSMRObject):
}
return json.dumps(output)
class MBusObjectPeak(DSMRObject):
@property
@@ -132,7 +133,9 @@ class MBusObjectPeak(DSMRObject):
return self.values[2]['unit']
def __str__(self):
output = "{}\t[{}] at {} occurred {}".format(str(self.value), str(self.unit), str(self.datetime.astimezone().isoformat()), str(self.occurred.astimezone().isoformat()))
output = "{}\t[{}] at {} occurred {}"\
.format(str(self.value), str(self.unit), str(self.datetime.astimezone().isoformat()),
str(self.occurred.astimezone().isoformat()))
return output
def to_json(self):
+4 -4
View File
@@ -244,10 +244,10 @@ class MaxDemandParser(DSMRObjectParser):
objects = []
count = int(values[0])
for i in range(1, count+1):
timestamp_month = ValueParser(timestamp).parse(values[i*3+1])
timestamp_occurred = ValueParser(timestamp).parse(values[i*3+1])
value = ValueParser(Decimal).parse(values[i*3+2])
for i in range(1, count + 1):
timestamp_month = ValueParser(timestamp).parse(values[i * 3 + 1])
timestamp_occurred = ValueParser(timestamp).parse(values[i * 3 + 1])
value = ValueParser(Decimal).parse(values[i * 3 + 2])
objects.append(MBusObjectPeak([timestamp_month, timestamp_occurred, value]))
return objects
+8
View File
@@ -240,6 +240,8 @@ SWEDEN = {
obis.P1_MESSAGE_TIMESTAMP: CosemParser(ValueParser(timestamp)),
obis.ELECTRICITY_IMPORTED_TOTAL: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_EXPORTED_TOTAL: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_REACTIVE_IMPORTED_TOTAL: CosemParser(ValueParser(Decimal)),
obis.ELECTRICITY_REACTIVE_EXPORTED_TOTAL: 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)),
@@ -248,6 +250,12 @@ SWEDEN = {
obis.INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_REACTIVE_POWER_L1_POSITIVE: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_REACTIVE_POWER_L1_NEGATIVE: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_REACTIVE_POWER_L2_POSITIVE: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_REACTIVE_POWER_L2_NEGATIVE: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_REACTIVE_POWER_L3_POSITIVE: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_REACTIVE_POWER_L3_NEGATIVE: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_VOLTAGE_L1: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_VOLTAGE_L2: CosemParser(ValueParser(Decimal)),
obis.INSTANTANEOUS_VOLTAGE_L3: CosemParser(ValueParser(Decimal)),
+2 -2
View File
@@ -4,10 +4,10 @@ setup(
name='dsmr-parser',
description='Library to parse Dutch Smart Meter Requirements (DSMR)',
author='Nigel Dokter and many others',
author_email='nigel@nldr.net',
author_email='mail@nldr.net',
license='MIT',
url='https://github.com/ndokter/dsmr_parser',
version='1.0.0',
version='1.1.0',
packages=find_packages(exclude=('test', 'test.*')),
install_requires=[
'pyserial>=3,<4',
-1
View File
@@ -246,7 +246,6 @@ class TelegramParserFluviusTest(unittest.TestCase):
assert isinstance(result[obis.BELGIUM_MBUS2_METER_READING1].value, Decimal)
assert result[obis.BELGIUM_MBUS2_METER_READING1].value == Decimal('872.234')
def test_checksum_valid(self):
# No exception is raised.
TelegramParser.validate_checksum(TELEGRAM_FLUVIUS_V171)
+17
View File
@@ -2,8 +2,25 @@
deps=
pytest
pytest-cov
pylama
pytest-asyncio
pytest-mock
dlms_cosem
commands=
py.test --cov=dsmr_parser test {posargs}
pylama dsmr_parser test
[pylama:dsmr_parser/clients/__init__.py]
ignore = W0611
[pylama:dsmr_parser/parsers.py]
ignore = W605
[pylama:test/example_telegrams.py]
ignore = E501
[pylama:pylint]
max_line_length = 120
[pylama:pycodestyle]
max_line_length = 120