Merge pull request #45 from lowdef/extend_filereader

Extend filereader
This commit is contained in:
Nigel Dokter 2020-02-03 17:31:15 +01:00 committed by GitHub
commit d423070853
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 111 additions and 71 deletions

View File

@ -1,5 +1,6 @@
import logging import logging
import fileinput import fileinput
import tailer
from dsmr_parser.clients.telegram_buffer import TelegramBuffer from dsmr_parser.clients.telegram_buffer import TelegramBuffer
from dsmr_parser.exceptions import ParseError, InvalidChecksumError from dsmr_parser.exceptions import ParseError, InvalidChecksumError
@ -8,6 +9,7 @@ from dsmr_parser.parsers import TelegramParser
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class FileReader(object): class FileReader(object):
""" """
Filereader to read and parse raw telegram strings from a file and instantiate Telegram objects Filereader to read and parse raw telegram strings from a file and instantiate Telegram objects
@ -73,6 +75,7 @@ class FileReader(object):
except ParseError as e: except ParseError as e:
logger.error('Failed to parse telegram: %s', e) logger.error('Failed to parse telegram: %s', e)
class FileInputReader(object): class FileInputReader(object):
""" """
Filereader to read and parse raw telegram strings from stdin or files specified at the commandline Filereader to read and parse raw telegram strings from stdin or files specified at the commandline
@ -120,3 +123,49 @@ class FileInputReader(object):
logger.warning(str(e)) logger.warning(str(e))
except ParseError as e: except ParseError as e:
logger.error('Failed to parse telegram: %s', e) logger.error('Failed to parse telegram: %s', e)
class FileTailReader(object):
"""
Filereader to read and parse raw telegram strings from the tail of a
given file and instantiate Telegram objects for each read telegram.
Usage python script "syphon_smartmeter_readings_stdin.py":
from dsmr_parser import telegram_specifications
from dsmr_parser.clients.filereader import FileTailReader
if __name__== "__main__":
infile = '/data/smartmeter/readings.txt'
filetail_reader = FileTailReader(
file = infile,
telegram_specification = telegram_specifications.V5
)
for telegram in filetail_reader.read_as_object():
print(telegram)
"""
def __init__(self, file, telegram_specification):
self._file = file
self.telegram_parser = TelegramParser(telegram_specification)
self.telegram_buffer = TelegramBuffer()
self.telegram_specification = telegram_specification
def read_as_object(self):
"""
Read complete DSMR telegram's from a files tail and return a Telegram object.
:rtype: generator
"""
with open(self._file, "rb") as file_handle:
for data in tailer.follow(file_handle):
str = data.decode()
self.telegram_buffer.append(str)
for telegram in self.telegram_buffer.get_all():
try:
yield 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)

View File

@ -59,6 +59,7 @@ def create_tcp_dsmr_reader(host, port, dsmr_version,
conn = loop.create_connection(protocol, host, port) conn = loop.create_connection(protocol, host, port)
return conn return conn
class DSMRProtocol(asyncio.Protocol): class DSMRProtocol(asyncio.Protocol):
"""Assemble and handle incoming data into complete DSM telegrams.""" """Assemble and handle incoming data into complete DSM telegrams."""

View File

@ -1,5 +1,6 @@
import dsmr_parser.obis_name_mapping import dsmr_parser.obis_name_mapping
class Telegram(object): class Telegram(object):
""" """
Container for raw and parsed telegram data. Container for raw and parsed telegram data.

View File

@ -3,7 +3,7 @@ import re
from ctypes import c_ushort from ctypes import c_ushort
from dsmr_parser.objects import MBusObject, CosemObject, Telegram from dsmr_parser.objects import MBusObject, CosemObject
from dsmr_parser.exceptions import ParseError, InvalidChecksumError from dsmr_parser.exceptions import ParseError, InvalidChecksumError
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -12,6 +12,7 @@ setup(
'pyserial>=3,<4', 'pyserial>=3,<4',
'pyserial-asyncio<1', 'pyserial-asyncio<1',
'pytz', 'pytz',
'Tailer==0.4.1'
], ],
entry_points={ entry_points={
'console_scripts': ['dsmr_console=dsmr_parser.__main__:console'] 'console_scripts': ['dsmr_console=dsmr_parser.__main__:console']

View File

@ -1,11 +1,5 @@
from decimal import Decimal
import datetime
import unittest
import pytz
from dsmr_parser import obis_references as obis
from dsmr_parser import telegram_specifications from dsmr_parser import telegram_specifications
from dsmr_parser.exceptions import InvalidChecksumError, ParseError from dsmr_parser.objects import Telegram
from dsmr_parser.objects import CosemObject, MBusObject, Telegram
from dsmr_parser.parsers import TelegramParser from dsmr_parser.parsers import TelegramParser
from example_telegrams import TELEGRAM_V4_2 from example_telegrams import TELEGRAM_V4_2
parser = TelegramParser(telegram_specifications.V4) parser = TelegramParser(telegram_specifications.V4)

View File

@ -1,30 +1,21 @@
from decimal import Decimal
import datetime
import unittest import unittest
import pytz
from dsmr_parser import obis_references as obis
from dsmr_parser import telegram_specifications from dsmr_parser import telegram_specifications
from dsmr_parser.exceptions import InvalidChecksumError, ParseError from dsmr_parser.objects import CosemObject
from dsmr_parser.objects import CosemObject, MBusObject, Telegram from dsmr_parser.objects import Telegram
from dsmr_parser.parsers import TelegramParser from dsmr_parser.parsers import TelegramParser
from test.example_telegrams import TELEGRAM_V4_2 from test.example_telegrams import TELEGRAM_V4_2
class TelegramTest(unittest.TestCase): class TelegramTest(unittest.TestCase):
""" Test instantiation of Telegram object """ """ Test instantiation of Telegram object """
def test_instantiate(self): def test_instantiate(self):
parser = TelegramParser(telegram_specifications.V4) parser = TelegramParser(telegram_specifications.V4)
#result = parser.parse(TELEGRAM_V4_2)
telegram = Telegram(TELEGRAM_V4_2, parser, telegram_specifications.V4) telegram = Telegram(TELEGRAM_V4_2, parser, telegram_specifications.V4)
# P1_MESSAGE_HEADER (1-3:0.2.8) # P1_MESSAGE_HEADER (1-3:0.2.8)
#assert isinstance(result[obis.P1_MESSAGE_HEADER], CosemObject) testitem = telegram.P1_MESSAGE_HEADER
#assert result[obis.P1_MESSAGE_HEADER].unit is None assert isinstance(testitem, CosemObject)
#assert isinstance(result[obis.P1_MESSAGE_HEADER].value, str) assert testitem.unit is None
#assert result[obis.P1_MESSAGE_HEADER].value == '50' assert testitem.value == '42'

11
tox.ini
View File

@ -1,5 +1,5 @@
[tox] [tox]
envlist = py34,py35,p36 envlist = py34,py35,py36,py37
[testenv] [testenv]
deps= deps=
@ -14,10 +14,13 @@ commands=
pylama dsmr_parser test pylama dsmr_parser test
[pylama:dsmr_parser/clients/__init__.py] [pylama:dsmr_parser/clients/__init__.py]
ignore = W0611,W0605 ignore = W0611
[pylama:dsmr_parser/parsers.py]
ignore = W605
[pylama:pylint] [pylama:pylint]
max_line_length = 100 max_line_length = 120
[pylama:pycodestyle] [pylama:pycodestyle]
max_line_length = 100 max_line_length = 120