diff --git a/dsmr_parser/exceptions.py b/dsmr_parser/exceptions.py index a5fa8f4..4babfd6 100644 --- a/dsmr_parser/exceptions.py +++ b/dsmr_parser/exceptions.py @@ -4,3 +4,7 @@ class ParseError(Exception): class InvalidChecksumError(ParseError): pass + + +class TelegramSpecificationMatchError(ParseError): + pass diff --git a/dsmr_parser/parsers.py b/dsmr_parser/parsers.py index 6a9f465..7d238b7 100644 --- a/dsmr_parser/parsers.py +++ b/dsmr_parser/parsers.py @@ -4,16 +4,18 @@ import re from PyCRC.CRC16 import CRC16 from dsmr_parser.objects import MBusObject, CosemObject -from dsmr_parser.exceptions import ParseError, InvalidChecksumError +from dsmr_parser.exceptions import ParseError, InvalidChecksumError, \ + TelegramSpecificationMatchError logger = logging.getLogger(__name__) class TelegramParser(object): - def __init__(self, telegram_specification, apply_checksum_validation=True): + def __init__(self, telegram_specification=None, apply_checksum_validation=True): """ - :param telegram_specification: determines how the telegram is parsed + :param telegram_specification: determines how the telegram is parsed. + Will attempt to autodetect if omitted. :param apply_checksum_validation: validate checksum if applicable for telegram DSMR version (v4 and up). :type telegram_specification: dict @@ -39,8 +41,10 @@ class TelegramParser(object): .. } :raises ParseError: - :raises InvalidChecksumError: """ + if not self.telegram_specification: + self.telegram_specification = \ + match_telegram_specification(telegram_data) if self.apply_checksum_validation \ and self.telegram_specification['checksum_support']: @@ -118,6 +122,11 @@ def match_telegram_specification(telegram_data): else: return specification + raise TelegramSpecificationMatchError( + 'Could automatically match telegram specification. Make sure the data' + 'is not corrupt. Alternatively manually specify one.' + ) + class DSMRObjectParser(object): """ diff --git a/test/test_match_telegram_specification.py b/test/test_match_telegram_specification.py index 357495a..6f5134f 100644 --- a/test/test_match_telegram_specification.py +++ b/test/test_match_telegram_specification.py @@ -1,5 +1,6 @@ import unittest +from dsmr_parser.exceptions import TelegramSpecificationMatchError from dsmr_parser.parsers import match_telegram_specification from dsmr_parser import telegram_specifications from test import example_telegrams @@ -22,3 +23,7 @@ class MatchTelegramSpecificationTest(unittest.TestCase): def test_v5(self): assert match_telegram_specification(example_telegrams.TELEGRAM_V5) \ == telegram_specifications.V5 + + def test_malformed_telegram(self): + with self.assertRaises(TelegramSpecificationMatchError): + match_telegram_specification(example_telegrams.TELEGRAM_V5[:-4]) diff --git a/test/test_parse_v2_2.py b/test/test_parse_v2_2.py index e7203ab..cba1a4d 100644 --- a/test/test_parse_v2_2.py +++ b/test/test_parse_v2_2.py @@ -12,6 +12,15 @@ from test.example_telegrams import TELEGRAM_V2_2 class TelegramParserV2_2Test(unittest.TestCase): """ Test parsing of a DSMR v2.2 telegram. """ + def test_telegram_specification_matching(self): + parser = TelegramParser() + parser.parse(TELEGRAM_V2_2) + + self.assertEqual( + parser.telegram_specification, + telegram_specifications.V2_2 + ) + def test_parse(self): parser = TelegramParser(telegram_specifications.V2_2) result = parser.parse(TELEGRAM_V2_2) diff --git a/test/test_parse_v3.py b/test/test_parse_v3.py index c50a86e..c583835 100644 --- a/test/test_parse_v3.py +++ b/test/test_parse_v3.py @@ -12,6 +12,15 @@ from test.example_telegrams import TELEGRAM_V3 class TelegramParserV3Test(unittest.TestCase): """ Test parsing of a DSMR v3 telegram. """ + def test_telegram_specification_matching(self): + parser = TelegramParser() + parser.parse(TELEGRAM_V3) + + self.assertEqual( + parser.telegram_specification, + telegram_specifications.V3 + ) + def test_parse(self): parser = TelegramParser(telegram_specifications.V3) result = parser.parse(TELEGRAM_V3) diff --git a/test/test_parse_v4_2.py b/test/test_parse_v4_2.py index 681783b..ba3ecbd 100644 --- a/test/test_parse_v4_2.py +++ b/test/test_parse_v4_2.py @@ -15,6 +15,15 @@ from test.example_telegrams import TELEGRAM_V4_2 class TelegramParserV4_2Test(unittest.TestCase): """ Test parsing of a DSMR v4.2 telegram. """ + def test_telegram_specification_matching(self): + parser = TelegramParser() + parser.parse(TELEGRAM_V4_2) + + self.assertEqual( + parser.telegram_specification, + telegram_specifications.V4 + ) + def test_parse(self): parser = TelegramParser(telegram_specifications.V4) result = parser.parse(TELEGRAM_V4_2) diff --git a/test/test_parse_v5.py b/test/test_parse_v5.py index 550fde9..b26cb60 100644 --- a/test/test_parse_v5.py +++ b/test/test_parse_v5.py @@ -16,6 +16,15 @@ from test.example_telegrams import TELEGRAM_V5 class TelegramParserV5Test(unittest.TestCase): """ Test parsing of a DSMR v5.x telegram. """ + def test_telegram_specification_matching(self): + parser = TelegramParser() + parser.parse(TELEGRAM_V5) + + self.assertEqual( + parser.telegram_specification, + telegram_specifications.V5 + ) + def test_parse(self): parser = TelegramParser(telegram_specifications.V5) result = parser.parse(TELEGRAM_V5)