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 fileinput
import tailer
from dsmr_parser.clients.telegram_buffer import TelegramBuffer
from dsmr_parser.exceptions import ParseError, InvalidChecksumError
@ -8,6 +9,7 @@ from dsmr_parser.parsers import TelegramParser
logger = logging.getLogger(__name__)
class FileReader(object):
"""
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:
logger.error('Failed to parse telegram: %s', e)
class FileInputReader(object):
"""
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))
except ParseError as 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)
return conn
class DSMRProtocol(asyncio.Protocol):
"""Assemble and handle incoming data into complete DSM telegrams."""

View File

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

View File

@ -3,7 +3,7 @@ import re
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
logger = logging.getLogger(__name__)

View File

@ -12,6 +12,7 @@ setup(
'pyserial>=3,<4',
'pyserial-asyncio<1',
'pytz',
'Tailer==0.4.1'
],
entry_points={
'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.exceptions import InvalidChecksumError, ParseError
from dsmr_parser.objects import CosemObject, MBusObject, Telegram
from dsmr_parser.objects import Telegram
from dsmr_parser.parsers import TelegramParser
from example_telegrams import TELEGRAM_V4_2
parser = TelegramParser(telegram_specifications.V4)

View File

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

11
tox.ini
View File

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