From 4afab70dc094871b6534131278b31826a4343c1e Mon Sep 17 00:00:00 2001 From: Johan Bloemberg Date: Sat, 12 Nov 2016 00:45:55 +0100 Subject: [PATCH 1/3] Add asyncio reader. --- dsmr_parser/serial.py | 48 +++++++++++++++++++++++++++++++++++++++++-- setup.py | 1 + 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/dsmr_parser/serial.py b/dsmr_parser/serial.py index 3e7aa70..0d716fd 100644 --- a/dsmr_parser/serial.py +++ b/dsmr_parser/serial.py @@ -1,5 +1,6 @@ import serial - +import asyncio +import serial_asyncio from dsmr_parser.parsers import TelegramParser, TelegramParserV2_2 SERIAL_SETTINGS_V2_2 = { @@ -33,9 +34,11 @@ def is_end_of_telegram(line): class SerialReader(object): + PORT_KEY = 'port' + def __init__(self, device, serial_settings, telegram_specification): self.serial_settings = serial_settings - self.serial_settings['port'] = device + self.serial_settings[self.PORT_KEY] = device if serial_settings is SERIAL_SETTINGS_V2_2: telegram_parser = TelegramParserV2_2 @@ -67,3 +70,44 @@ class SerialReader(object): if is_end_of_telegram(line): yield self.telegram_parser.parse(telegram) telegram = [] + +class AsyncSerialReader(SerialReader): + """Serial reader using asyncio pyserial.""" + + PORT_KEY = 'url' + + @asyncio.coroutine + def read(self, queue): + """ + Read complete DSMR telegram's from the serial interface and parse it + into CosemObject's and MbusObject's. + + Instead of being a generator, values are pushed to provided queue for + asynchronous processing. + + :rtype Generator/Async + """ + # create Serial StreamReader + conn = serial_asyncio.open_serial_connection(**self.serial_settings) + reader, _ = yield from conn + + telegram = [] + + while True: + # read line if available or give control back to loop until + # new data has arrived + line = yield from reader.readline() + line = line.decode('ascii') + + # Telegrams need to be complete because the values belong to a + # particular reading and can also be related to eachother. + if not telegram and not is_start_of_telegram(line): + continue + + telegram.append(line) + + if is_end_of_telegram(line): + # push new parsed telegram onto queue + queue.put_nowait(self.telegram_parser.parse(telegram)) + telegram = [] + diff --git a/setup.py b/setup.py index d02d7a3..cc79d2d 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,7 @@ setup( packages=find_packages(), install_requires=[ 'pyserial>=3,<4', + 'pyserial-asyncio<1' 'pytz' ], entry_points={ From 9363840042c54551958855d7936d92cab5f0a382 Mon Sep 17 00:00:00 2001 From: Johan Bloemberg Date: Sat, 12 Nov 2016 01:34:32 +0100 Subject: [PATCH 2/3] Project maintenance. --- CHANGELOG.rst | 4 ++++ README.rst | 2 +- setup.py | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 14fc532..dbebfea 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,5 +1,9 @@ Change Log ---------- +**0.3** + +- Added asyncio reader for non-blocking reads. + **0.2** (2016-11-08) - User https://github.com/aequitas added support for DMSR version 2.2 diff --git a/README.rst b/README.rst index f63d373..23aff2f 100644 --- a/README.rst +++ b/README.rst @@ -11,7 +11,7 @@ also includes a serial client to directly read and parse smart meter data. Features -------- -DSMR Parser currently supports DSMR versions 2.2 and 4.x. It has been tested with Python 3.5 +DSMR Parser currently supports DSMR versions 2.2 and 4.x. It has been tested with Python 3.5 and 3.4. Examples diff --git a/setup.py b/setup.py index cc79d2d..855f005 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( author='Nigel Dokter', author_email='nigeldokter@gmail.com', url='https://github.com/ndokter/dsmr_parser', - version='0.2', + version='0.3', packages=find_packages(), install_requires=[ 'pyserial>=3,<4', From e3c8c921986cac05a75223c2b53cf75669151c20 Mon Sep 17 00:00:00 2001 From: Johan Bloemberg Date: Sat, 12 Nov 2016 01:36:36 +0100 Subject: [PATCH 3/3] Linting and tpyo --- dsmr_parser/serial.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dsmr_parser/serial.py b/dsmr_parser/serial.py index 0d716fd..6f47b1c 100644 --- a/dsmr_parser/serial.py +++ b/dsmr_parser/serial.py @@ -71,6 +71,7 @@ class SerialReader(object): yield self.telegram_parser.parse(telegram) telegram = [] + class AsyncSerialReader(SerialReader): """Serial reader using asyncio pyserial.""" @@ -110,4 +111,3 @@ class AsyncSerialReader(SerialReader): # push new parsed telegram onto queue queue.put_nowait(self.telegram_parser.parse(telegram)) telegram = [] - diff --git a/setup.py b/setup.py index 855f005..3a919fa 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ setup( packages=find_packages(), install_requires=[ 'pyserial>=3,<4', - 'pyserial-asyncio<1' + 'pyserial-asyncio<1', 'pytz' ], entry_points={