Files
dsmr2mqtt/lib/dsmr_parser_lib/dsmr_parser/clients/telegram_buffer.py
Ard Kuijpers ccf189662d Add 'lib/dsmr_parser_lib/' from commit 'f9e188812fbaee90974a3cddf201bbb40278fd9a'
git-subtree-dir: lib/dsmr_parser_lib
git-subtree-mainline: 4c0b801f96
git-subtree-split: f9e188812f
2020-06-03 14:15:43 +02:00

58 lines
1.8 KiB
Python

import re
class TelegramBuffer(object):
"""
Used as a buffer for a stream of telegram data. Constructs full telegram
strings from the buffered data and returns it.
"""
def __init__(self):
self._buffer = ''
def get_all(self):
"""
Remove complete telegrams from buffer and yield them.
:rtype generator:
"""
for telegram in self._find_telegrams():
self._remove(telegram)
yield telegram
def append(self, data):
"""
Add telegram data to buffer.
:param str data: chars, lines or full telegram strings of telegram data
"""
self._buffer += data
def _remove(self, telegram):
"""
Remove telegram from buffer and incomplete data preceding it. This
is easier than validating the data before adding it to the buffer.
:param str telegram:
:return:
"""
# Remove data leading up to the telegram and the telegram itself.
index = self._buffer.index(telegram) + len(telegram)
self._buffer = self._buffer[index:]
def _find_telegrams(self):
"""
Find complete telegrams in buffer from start ('/') till ending
checksum ('!AB12\r\n').
:rtype: list
"""
# - Match all characters after start of telegram except for the start
# itself again '^\/]+', which eliminates incomplete preceding telegrams.
# - Do non greedy match using '?' so start is matched up to the first
# checksum that's found.
# - The checksum is optional '{0,4}' because not all telegram versions
# support it.
return re.findall(
r'\/[^\/]+?\![A-F0-9]{0,4}\0?\r\n',
self._buffer,
re.DOTALL
)