commit
						d61f2229c8
					
				| @ -63,6 +63,6 @@ ELECTRICITY_DELIVERED_TARIFF_ALL = ( | ||||
| 
 | ||||
| # Alternate codes for foreign countries. | ||||
| BELGIUM_HOURLY_GAS_METER_READING = r'\d-\d:24\.2\.3.+?\r\n'  # Different code, same format. | ||||
| LUXEMBOURG_EQUIPMENT_IDENTIFIER = r'\d-\d:42\.0\.0.+?\r\n' # Logical device name | ||||
| LUXEMBOURG_EQUIPMENT_IDENTIFIER = r'\d-\d:42\.0\.0.+?\r\n'  # Logical device name | ||||
| LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL = r'\d-\d:1\.8\.0.+?\r\n'  # Total imported energy register (P+) | ||||
| LUXEMBOURG_ELECTRICITY_DELIVERED_TARIFF_GLOBAL = r'\d-\d:2\.8\.0.+?\r\n'  # Total exported energy register (P-) | ||||
|  | ||||
| @ -225,6 +225,10 @@ class ProfileGenericParser(DSMRObjectParser): | ||||
|         self.parsers_for_unidentified = parsers_for_unidentified | ||||
| 
 | ||||
|     def _is_line_wellformed(self, line, values): | ||||
|         if values and (len(values) == 1) and (values[0] == ''): | ||||
|             # special case: single empty parentheses (indicated by empty string) | ||||
|             return True | ||||
| 
 | ||||
|         if values and (len(values) >= 2) and (values[0].isdigit()): | ||||
|             buffer_length = int(values[0]) | ||||
|             return (buffer_length <= 10) and (len(values) == (buffer_length * 2 + 2)) | ||||
| @ -232,6 +236,9 @@ class ProfileGenericParser(DSMRObjectParser): | ||||
|             return False | ||||
| 
 | ||||
|     def _parse_values(self, values): | ||||
|         if values and (len(values) == 1) and (values[0] is None): | ||||
|             # special case: single empty parentheses; make sure empty ProfileGenericObject is created | ||||
|             values = [0, None]  # buffer_length=0, buffer_value_obis_ID=None | ||||
|         buffer_length = int(values[0]) | ||||
|         buffer_value_obis_ID = values[1] | ||||
|         if (buffer_length > 0): | ||||
|  | ||||
| @ -241,7 +241,6 @@ class TelegramParserV5Test(unittest.TestCase): | ||||
| 
 | ||||
|     def test_checksum_missing(self): | ||||
|         # Remove the checksum value causing a ParseError. | ||||
|         corrupted_telegram = TELEGRAM_V5.replace('!87B3\r\n', '') | ||||
| 
 | ||||
|         corrupted_telegram = TELEGRAM_V5.replace('!6EEE\r\n', '') | ||||
|         with self.assertRaises(ParseError): | ||||
|             TelegramParser.validate_checksum(corrupted_telegram) | ||||
|  | ||||
							
								
								
									
										89
									
								
								test/test_parser_corner_cases.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								test/test_parser_corner_cases.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | ||||
| import unittest | ||||
| 
 | ||||
| from dsmr_parser import telegram_specifications | ||||
| 
 | ||||
| from dsmr_parser.objects import Telegram | ||||
| from dsmr_parser.objects import ProfileGenericObject | ||||
| from dsmr_parser.parsers import TelegramParser | ||||
| from dsmr_parser.parsers import ProfileGenericParser | ||||
| from dsmr_parser.profile_generic_specifications import BUFFER_TYPES | ||||
| from dsmr_parser.profile_generic_specifications import PG_HEAD_PARSERS | ||||
| from dsmr_parser.profile_generic_specifications import PG_UNIDENTIFIED_BUFFERTYPE_PARSERS | ||||
| from test.example_telegrams import TELEGRAM_V5 | ||||
| 
 | ||||
| 
 | ||||
| class TestParserCornerCases(unittest.TestCase): | ||||
|     """ Test instantiation of Telegram object """ | ||||
| 
 | ||||
|     def test_power_event_log_empty_1(self): | ||||
|         # POWER_EVENT_FAILURE_LOG (1-0:99.97.0) | ||||
|         parser = TelegramParser(telegram_specifications.V5) | ||||
|         telegram = Telegram(TELEGRAM_V5, parser, telegram_specifications.V5) | ||||
| 
 | ||||
|         object_type = ProfileGenericObject | ||||
|         testitem = telegram.POWER_EVENT_FAILURE_LOG | ||||
|         assert isinstance(testitem, object_type) | ||||
|         assert testitem.buffer_length == 0 | ||||
|         assert testitem.buffer_type == '0-0:96.7.19' | ||||
|         buffer = testitem.buffer | ||||
|         assert isinstance(testitem.buffer, list) | ||||
|         assert len(buffer) == 0 | ||||
| 
 | ||||
|     def test_power_event_log_empty_2(self): | ||||
|         pef_parser = ProfileGenericParser(BUFFER_TYPES, PG_HEAD_PARSERS, PG_UNIDENTIFIED_BUFFERTYPE_PARSERS) | ||||
|         object_type = ProfileGenericObject | ||||
| 
 | ||||
|         # Power Event Log with 0 items and no object type | ||||
|         pefl_line = r'1-0:99.97.0(0)()\r\n' | ||||
|         testitem = pef_parser.parse(pefl_line) | ||||
| 
 | ||||
|         assert isinstance(testitem, object_type) | ||||
|         assert testitem.buffer_length == 0 | ||||
|         assert testitem.buffer_type is None | ||||
|         buffer = testitem.buffer | ||||
|         assert isinstance(testitem.buffer, list) | ||||
|         assert len(buffer) == 0 | ||||
|         assert testitem.values == [{'value': 0, 'unit': None}, {'value': None, 'unit': None}] | ||||
|         json = testitem.to_json() | ||||
|         assert json == '{"buffer_length": 0, "buffer_type": null, "buffer": []}' | ||||
| 
 | ||||
|     def test_power_event_log_null_values(self): | ||||
|         pef_parser = ProfileGenericParser(BUFFER_TYPES, PG_HEAD_PARSERS, PG_UNIDENTIFIED_BUFFERTYPE_PARSERS) | ||||
|         object_type = ProfileGenericObject | ||||
| 
 | ||||
|         # Power Event Log with 1 item and no object type and nno values for the item | ||||
|         pefl_line = r'1-0:99.97.0(1)()()()\r\n' | ||||
|         testitem = pef_parser.parse(pefl_line) | ||||
| 
 | ||||
|         assert isinstance(testitem, object_type) | ||||
|         assert testitem.buffer_length == 1 | ||||
|         assert testitem.buffer_type is None | ||||
|         buffer = testitem.buffer | ||||
|         assert isinstance(testitem.buffer, list) | ||||
|         assert len(buffer) == 1 | ||||
|         assert testitem.values == [{'value': 1, 'unit': None}, {'value': None, 'unit': None}, | ||||
|                                    {'value': None, 'unit': None}, {'value': None, 'unit': None}] | ||||
|         json = testitem.to_json() | ||||
|         assert json == \ | ||||
|                '{"buffer_length": 1, "buffer_type": null, "buffer": [{"datetime": null, "value": null, "unit": null}]}' | ||||
| 
 | ||||
|     def test_power_event_log_brackets_only(self): | ||||
|         # POWER_EVENT_FAILURE_LOG (1-0:99.97.0) | ||||
|         # Issue 57 | ||||
|         # Test of an ill formatted empty POWER_EVENT_FAILURE_LOG, observed on some smartmeters | ||||
|         # The idea is that instead of failing, the parser converts it to an empty POWER_EVENT_FAILURE_LOG | ||||
|         pef_parser = ProfileGenericParser(BUFFER_TYPES, PG_HEAD_PARSERS, PG_UNIDENTIFIED_BUFFERTYPE_PARSERS) | ||||
|         object_type = ProfileGenericObject | ||||
| 
 | ||||
|         pefl_line = r'1-0:99.97.0()\r\n' | ||||
|         testitem = pef_parser.parse(pefl_line) | ||||
| 
 | ||||
|         assert isinstance(testitem, object_type) | ||||
|         assert testitem.buffer_length == 0 | ||||
|         assert testitem.buffer_type is None | ||||
|         buffer = testitem.buffer | ||||
|         assert isinstance(testitem.buffer, list) | ||||
|         assert len(buffer) == 0 | ||||
|         assert testitem.values == [{'value': 0, 'unit': None}, {'value': None, 'unit': None}] | ||||
|         json = testitem.to_json() | ||||
|         assert json == '{"buffer_length": 0, "buffer_type": null, "buffer": []}' | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user