issue-51-telegram refining

This commit is contained in:
Nigel Dokter 2023-02-18 15:04:31 +01:00
parent 0a6316e155
commit 36705f99ca
6 changed files with 101 additions and 60 deletions

View File

@ -1,70 +1,74 @@
Change Log
----------
**1.2.0** (2023-02-18)
- Improved gas meter (mbus devices) support and replaced Telegram dictionary with backwards compatible object (`PR #121 <https://github.com/ndokter/dsmr_parser/pull/121>`_ by `ndokter <https://github.com/ndokter>`_)
**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>`_)
- Add instantaneous reactive power + fixed swapped reactive total import export (`PR #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 #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>`_)
- Added support for Python 3.11 and dropped support for Python 3.6 (`PR #112 <https://github.com/ndokter/dsmr_parser/pull/112>`_ by `dennissiemensma <https://github.com/dennissiemensma>`_)
- Add support for Fluvius V1.7.1 DSMR messages (`PR #110 <https://github.com/ndokter/dsmr_parser/pull/113>`_ by `dupondje <https://github.com/dupondje>`_)
**0.34** (2022-10-19)
- Adds support for the Sagemcom T210-D-r smart meter (`pull request #110 <https://github.com/ndokter/dsmr_parser/pull/110>`_).
- Adds support for the Sagemcom T210-D-r smart meter (`PR #110 <https://github.com/ndokter/dsmr_parser/pull/110>`_).
**0.33** (2022-04-20)
- Test Python 3.10 in CI + legacy badge fix (`pull request #105 <https://github.com/ndokter/dsmr_parser/pull/105>`_).
- Update telegram_specifications.py (`pull request #106 <https://github.com/ndokter/dsmr_parser/pull/106>`_).
- Improve compatiblity with Belgian standard (`pull request #107 <https://github.com/ndokter/dsmr_parser/pull/107>`_).
- Improve documentation asyncio (`pull request #63 <https://github.com/ndokter/dsmr_parser/pull/63>`_).
- Test Python 3.10 in CI + legacy badge fix (`PR #105 <https://github.com/ndokter/dsmr_parser/pull/105>`_).
- Update telegram_specifications.py (`PR #106 <https://github.com/ndokter/dsmr_parser/pull/106>`_).
- Improve compatiblity with Belgian standard (`PR #107 <https://github.com/ndokter/dsmr_parser/pull/107>`_).
- Improve documentation asyncio (`PR #63 <https://github.com/ndokter/dsmr_parser/pull/63>`_).
**0.32** (2022-01-04)
- Support DSMR data read via RFXtrx with integrated P1 reader (`pull request #98 <https://github.com/ndokter/dsmr_parser/pull/98>`_).
- Support DSMR data read via RFXtrx with integrated P1 reader (`PR #98 <https://github.com/ndokter/dsmr_parser/pull/98>`_).
**0.31** (2021-11-21)
- Support for (German) EasyMeter Q3D using COM-1 Ethernet Gateway (`pull request #92 <https://github.com/ndokter/dsmr_parser/pull/92>`_).
- Support for (German) EasyMeter Q3D using COM-1 Ethernet Gateway (`PR #92 <https://github.com/ndokter/dsmr_parser/pull/92>`_).
**0.30** (2021-08-18)
- Add support for Swedish smart meters (`pull request #86 <https://github.com/ndokter/dsmr_parser/pull/86>`_).
- Add support for Swedish smart meters (`PR #86 <https://github.com/ndokter/dsmr_parser/pull/86>`_).
**0.29** (2021-04-18)
- Add value and unit properties to ProfileGenericObject to make sure that code like iterators that rely on that do not break (`pull request #71 <https://github.com/ndokter/dsmr_parser/pull/71>`_).
Remove deprecated asyncio coroutine decorator (`pull request #76 <https://github.com/ndokter/dsmr_parser/pull/76>`_).
- Add value and unit properties to ProfileGenericObject to make sure that code like iterators that rely on that do not break (`PR #71 <https://github.com/ndokter/dsmr_parser/pull/71>`_).
Remove deprecated asyncio coroutine decorator (`PR #76 <https://github.com/ndokter/dsmr_parser/pull/76>`_).
**0.28** (2021-02-21)
- Optional keep alive monitoring for TCP/IP connections (`pull request #73 <https://github.com/ndokter/dsmr_parser/pull/73>`_).
- Catch parse errors in TelegramParser, ignore lines that can not be parsed (`pull request #74 <https://github.com/ndokter/dsmr_parser/pull/74>`_).
- Optional keep alive monitoring for TCP/IP connections (`PR #73 <https://github.com/ndokter/dsmr_parser/pull/73>`_).
- Catch parse errors in TelegramParser, ignore lines that can not be parsed (`PR #74 <https://github.com/ndokter/dsmr_parser/pull/74>`_).
**0.27** (2020-12-24)
- fix for empty parentheses in ProfileGenericParser (redone) (`pull request #69 <https://github.com/ndokter/dsmr_parser/pull/69>`_).
- fix for empty parentheses in ProfileGenericParser (redone) (`PR #69 <https://github.com/ndokter/dsmr_parser/pull/69>`_).
**0.26** (2020-12-15)
- reverted fix for empty parentheses in ProfileGenericParser (`pull request #68 <https://github.com/ndokter/dsmr_parser/pull/68>`_).
- reverted fix for empty parentheses in ProfileGenericParser (`PR #68 <https://github.com/ndokter/dsmr_parser/pull/68>`_).
**0.25** (2020-12-14)
- fix for empty parentheses in ProfileGenericParser (`pull request #57 <https://github.com/ndokter/dsmr_parser/pull/57>`_).
- fix for empty parentheses in ProfileGenericParser (`PR #57 <https://github.com/ndokter/dsmr_parser/pull/57>`_).
**0.24** (2020-11-27)
- Add Luxembourg equipment identifier (`pull request #62 <https://github.com/ndokter/dsmr_parser/pull/62>`_).
- Add Luxembourg equipment identifier (`PR #62 <https://github.com/ndokter/dsmr_parser/pull/62>`_).
**0.23** (2020-11-07)
- Resolved issue with x-x:24.3.0 where it contains non-integer character (`pull request #61 <https://github.com/ndokter/dsmr_parser/pull/61>`_).
- Tests are not installed anymore (`pull request #59 <https://github.com/ndokter/dsmr_parser/pull/59>`_).
- Example telegram improvement (`pull request #58 <https://github.com/ndokter/dsmr_parser/pull/58>`_).
- Resolved issue with x-x:24.3.0 where it contains non-integer character (`PR #61 <https://github.com/ndokter/dsmr_parser/pull/61>`_).
- Tests are not installed anymore (`PR #59 <https://github.com/ndokter/dsmr_parser/pull/59>`_).
- Example telegram improvement (`PR #58 <https://github.com/ndokter/dsmr_parser/pull/58>`_).
**0.22** (2020-08-23)
@ -92,40 +96,40 @@ Remove deprecated asyncio coroutine decorator (`pull request #76 <https://github
**0.18** (2020-01-28)
- PyCRC replacement (`pull request #48 <https://github.com/ndokter/dsmr_parser/pull/48>`_).
- PyCRC replacement (`PR #48 <https://github.com/ndokter/dsmr_parser/pull/48>`_).
**0.17** (2019-12-21)
- Add a true telegram object (`pull request #40 <https://github.com/ndokter/dsmr_parser/pull/40>`_).
- Add a true telegram object (`PR #40 <https://github.com/ndokter/dsmr_parser/pull/40>`_).
**0.16** (2019-12-21)
- Add support for Belgian and Smarty meters (`pull request #44 <https://github.com/ndokter/dsmr_parser/pull/44>`_).
- Add support for Belgian and Smarty meters (`PR #44 <https://github.com/ndokter/dsmr_parser/pull/44>`_).
**0.15** (2019-12-12)
- Fixed asyncio loop issue (`pull request #43 <https://github.com/ndokter/dsmr_parser/pull/43>`_).
- Fixed asyncio loop issue (`PR #43 <https://github.com/ndokter/dsmr_parser/pull/43>`_).
**0.14** (2019-10-08)
- Changed serial reading to reduce CPU usage (`pull request #37 <https://github.com/ndokter/dsmr_parser/pull/37>`_).
- Changed serial reading to reduce CPU usage (`PR #37 <https://github.com/ndokter/dsmr_parser/pull/37>`_).
**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>`_).
- Fix DSMR v5.0 serial settings which were not used (`PR #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>`_).
- Add serial settings for DSMR v5.0 (`PR #31 <https://github.com/ndokter/dsmr_parser/pull/31>`_).
- Lux-creos-obis-1.8.0 (`PR #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>`_)
- NULL value fix in checksum (`PR #26 <https://github.com/ndokter/dsmr_parser/pull/26>`_)
**0.10** (2017-06-05)
- bugfix: don't force full telegram signatures (`pull request #25 <https://github.com/ndokter/dsmr_parser/pull/25>`_)
- bugfix: don't force full telegram signatures (`PR #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
@ -145,7 +149,7 @@ Remove deprecated asyncio coroutine decorator (`pull request #76 <https://github
**0.7** (2017-01-14)
- Internal refactoring related to the way clients feed their data into the parse module. Clients can now supply the telegram data in single characters, lines (which was common) or complete telegram strings. (`pull request #17 <https://github.com/ndokter/dsmr_parser/pull/17>`_)
- Internal refactoring related to the way clients feed their data into the parse module. Clients can now supply the telegram data in single characters, lines (which was common) or complete telegram strings. (`PR #17 <https://github.com/ndokter/dsmr_parser/pull/17>`_)
**IMPORTANT: this release has the following backwards incompatible changes:**
@ -155,8 +159,8 @@ Remove deprecated asyncio coroutine decorator (`pull request #76 <https://github
**0.6** (2017-01-04)
- Fixed bug in CRC checksum verification for the asyncio client (`pull request #15 <https://github.com/ndokter/dsmr_parser/pull/15>`_)
- Support added for TCP connections using the asyncio client (`pull request #12 <https://github.com/ndokter/dsmr_parser/pull/12/>`_)
- Fixed bug in CRC checksum verification for the asyncio client (`PR #15 <https://github.com/ndokter/dsmr_parser/pull/15>`_)
- Support added for TCP connections using the asyncio client (`PR #12 <https://github.com/ndokter/dsmr_parser/pull/12/>`_)
**0.5** (2016-12-29)
@ -164,16 +168,16 @@ Remove deprecated asyncio coroutine decorator (`pull request #76 <https://github
**0.4** (2016-11-21)
- DSMR v2.2 serial settings now uses parity serial.EVEN by default (`pull request #5 <https://github.com/ndokter/dsmr_parser/pull/5>`_)
- improved asyncio reader and improve it's error handling (`pull request #8 <https://github.com/ndokter/dsmr_parser/pull/8>`_)
- DSMR v2.2 serial settings now uses parity serial.EVEN by default (`PR #5 <https://github.com/ndokter/dsmr_parser/pull/5>`_)
- improved asyncio reader and improve it's error handling (`PR #8 <https://github.com/ndokter/dsmr_parser/pull/8>`_)
**0.3** (2016-11-12)
- asyncio reader for non-blocking reads (`pull request #3 <https://github.com/ndokter/dsmr_parser/pull/3>`_)
- asyncio reader for non-blocking reads (`PR #3 <https://github.com/ndokter/dsmr_parser/pull/3>`_)
**0.2** (2016-11-08)
- support for DMSR version 2.2 (`pull request #2 <https://github.com/ndokter/dsmr_parser/pull/2>`_)
- support for DMSR version 2.2 (`PR #2 <https://github.com/ndokter/dsmr_parser/pull/2>`_)
**0.1** (2016-08-22)

View File

@ -169,9 +169,9 @@ However, if we construct a mock TelegramParser that just returns the already par
Parsing module usage
--------------------
The parsing module accepts complete unaltered telegram strings and parses these
into a Telegram object. This previously was a dictionary, but the Telegram object is mostly compatible.
into a Telegram object.
Getting full telegrams from a bytestream can be made easier by using the TelegramBuffer helper class.
Tip: getting full telegrams from a bytestream can be made easier by using the TelegramBuffer helper class.
.. code-block:: python
@ -214,6 +214,8 @@ Telegram object
A Telegram has attributes for all the parsed values according to the given telegram specification. Each value is a DsmrObject which have a 'value' and 'unit' property. MBusObject's, which are DsmrObject's as well 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'.
Note: Telegram extends dictionary, which done for backwards compatibility. The use of keys (e.g. `telegram[obis_references.CURRENT_ELECTRICITY_USAGE]`) is deprecated.
Below are some examples on how to get the meter data. Alternatively check out the following unit test for a complete example: TelegramParserV5Test.test_parse
.. code-block:: python
@ -233,18 +235,55 @@ Below are some examples on how to get the meter data. Alternatively check out th
print(telegram.CURRENT_ELECTRICITY_USAGE.value) # Decimal('2.027')
print(telegram.CURRENT_ELECTRICITY_USAGE.unit) # 'kW'
# All Mbus device readings like gas meters and water meters can be retrieved as follows:
mbus_devices = telegram.get_mbus_devices()
# All Mbus device readings like gas meters and water meters can be retrieved as follows. This
# returns a list of MbusDevice objects:
mbus_devices = telegram.MBUS_DEVICES
# A specific device based on the channel the device is connected to can be retrieved as follows:
# A specific MbusDevice based on the channel it's connected to, can be retrieved as follows:
mbus_device = telegram.get_mbus_device_by_channel(1)
print(mbus_device.DEVICE_TYPE.value) # 3
print(mbus_device.EQUIPMENT_IDENTIFIER_GAS.value) # '4730303339303031393336393930363139'
print(mbus_device.HOURLY_GAS_METER_READING.value) # Decimal('246.138')
# A deprecated way of getting the values is by key
# DEPRECATED: the dictionary approach of getting the values by key or `.items()' or '.get() is deprecated
telegram[obis_references.CURRENT_ELECTRICITY_USAGE]
The telegram object has an iterator, can be used to find all the information elements in the current telegram:
.. code-block:: python
[attr for attr, value in telegram]
Out[11]:
['P1_MESSAGE_HEADER',
'P1_MESSAGE_TIMESTAMP',
'EQUIPMENT_IDENTIFIER',
'ELECTRICITY_USED_TARIFF_1',
'ELECTRICITY_USED_TARIFF_2',
'ELECTRICITY_DELIVERED_TARIFF_1',
'ELECTRICITY_DELIVERED_TARIFF_2',
'ELECTRICITY_ACTIVE_TARIFF',
'CURRENT_ELECTRICITY_USAGE',
'CURRENT_ELECTRICITY_DELIVERY',
'LONG_POWER_FAILURE_COUNT',
'VOLTAGE_SAG_L1_COUNT',
'VOLTAGE_SAG_L2_COUNT',
'VOLTAGE_SAG_L3_COUNT',
'VOLTAGE_SWELL_L1_COUNT',
'VOLTAGE_SWELL_L2_COUNT',
'VOLTAGE_SWELL_L3_COUNT',
'TEXT_MESSAGE_CODE',
'TEXT_MESSAGE',
'DEVICE_TYPE',
'INSTANTANEOUS_ACTIVE_POWER_L1_POSITIVE',
'INSTANTANEOUS_ACTIVE_POWER_L2_POSITIVE',
'INSTANTANEOUS_ACTIVE_POWER_L3_POSITIVE',
'INSTANTANEOUS_ACTIVE_POWER_L1_NEGATIVE',
'INSTANTANEOUS_ACTIVE_POWER_L2_NEGATIVE',
'INSTANTANEOUS_ACTIVE_POWER_L3_NEGATIVE',
'EQUIPMENT_IDENTIFIER_GAS',
'HOURLY_GAS_METER_READING']
Installation
------------

View File

@ -1,5 +1,4 @@
from decimal import Decimal
from operator import attrgetter
import datetime
import json
@ -57,16 +56,15 @@ class Telegram(dict):
mbus_device = self._mbus_channel_devices[channel_id]
mbus_device.add(obis_reference, dsmr_object)
def get_mbus_devices(self):
"""
Return MbusDevice objects which are used for water, heat and gas meters.
"""
mbus_devices = self._mbus_channel_devices.values()
mbus_devices = sorted(mbus_devices, key=attrgetter('channel_id'))
return mbus_devices
@property
def MBUS_DEVICES(self):
""" Return MbusDevice objects which are used for water, heat and gas meters. """
return list(self._mbus_channel_devices.values())
def get_mbus_device_by_channel(self, channel_id):
"""
:rtype: MbusDevice|None
"""
return self._mbus_channel_devices.get(channel_id)
def __len__(self):

View File

@ -7,7 +7,7 @@ setup(
author_email='mail@nldr.net',
license='MIT',
url='https://github.com/ndokter/dsmr_parser',
version='1.1.0',
version='1.2.0',
packages=find_packages(exclude=('test', 'test.*')),
install_requires=[
'pyserial>=3,<4',

View File

@ -338,10 +338,10 @@ class TelegramTest(unittest.TestCase):
self.assertEqual(obis_name, obis_name_mapping.EN[obis_references.P1_MESSAGE_HEADER])
self.assertEqual(dsmr_object.value, '50')
def test_get_mbus_devices(self):
def test_mbus_devices(self):
parser = TelegramParser(telegram_specifications.V5)
telegram = parser.parse(TELEGRAM_V5_TWO_MBUS)
mbus_devices = telegram.get_mbus_devices()
mbus_devices = telegram.MBUS_DEVICES
self.assertEqual(len(mbus_devices), 2)
@ -373,12 +373,12 @@ class TelegramTest(unittest.TestCase):
parser = TelegramParser(telegram_specifications.V5, apply_checksum_validation=False)
telegram = parser.parse('')
self.assertEqual(telegram.get_mbus_devices(), [])
self.assertEqual(telegram.MBUS_DEVICES, [])
self.assertIsNone(telegram.get_mbus_device_by_channel(1))
# Because of a bug related to incorrect use of defaultdict,
# test again for unwanted side effects
self.assertEqual(telegram.get_mbus_devices(), [])
self.assertEqual(telegram.MBUS_DEVICES, [])
def test_to_json(self):
parser = TelegramParser(telegram_specifications.V5)

View File

@ -213,7 +213,7 @@ class TelegramParserV5Test(unittest.TestCase):
# There's only one Mbus device (gas meter) in this case. Alternatively
# use get_mbget_mbus_device_by_channel
gas_meter_devices = telegram.get_mbus_devices()
gas_meter_devices = telegram.MBUS_DEVICES
gas_meter_device = gas_meter_devices[0]
# EQUIPMENT_IDENTIFIER_GAS (0-x:96.1.0)