From ebe61f151b3a2e8d8732dea9d160103cf1975314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Gr=C3=BCndger?= Date: Sat, 19 Apr 2025 09:06:58 +0200 Subject: [PATCH] Catch exception while parsing the APRS comment (fixes #126) --- CHANGELOG.md | 13 +++++++++---- ogn/parser/parse.py | 22 ++++++++++++---------- tests/parser/test_parse.py | 6 +++++- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c1482e..58f7d73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,17 @@ # CHANGELOG -## 1.2.3: - 2024-04-01 -- parser: Add Microtrak parser +======= +## 1.3.0: - 2025-04-19 +- parser: Handle messages that do not conform to the "ogn-aprs-protocol" specification/implementation (fixes #126) +- Moved dependency management to to poetry +- Added github action pipeline for automated testing and publishing -## 1.2.2: - 2024-03-31 +## 1.2.3: - 2024-04-01 (not released on PyPI) +- parser: Added support for OGNMTK (Microtrak) beacons + +## 1.2.2: - 2024-03-31 (not released on PyPI) - client: If no reference_timestamp provided use timestamp from APRS server (fixes #85) - parser: Handle dst_calls 'OGFLR6' (protocol 6) and 'OGFLR7' (protocol 7) like 'OGFLR' (fixes #123) -- parser: Added support for OGNMTK (Microtrak) beacons ## 1.2.1: - 2021-06-06 - client: Added peer IP to log messages diff --git a/ogn/parser/parse.py b/ogn/parser/parse.py index 8c798c9..3703a00 100644 --- a/ogn/parser/parse.py +++ b/ogn/parser/parse.py @@ -1,9 +1,8 @@ -import re from datetime import datetime from ogn.parser.utils import createTimestamp, parseAngle, KNOTS_TO_MS, KPH_TO_MS, FEETS_TO_METER, INCH_TO_MM, fahrenheit_to_celsius, CheapRuler, normalized_quality from ogn.parser.pattern import PATTERN_APRS, PATTERN_APRS_POSITION, PATTERN_APRS_POSITION_WEATHER, PATTERN_APRS_STATUS, PATTERN_SERVER -from ogn.parser.exceptions import AprsParseError +from ogn.parser.exceptions import AprsParseError, OgnParseError from ogn.parser.aprs_comment.ogn_parser import OgnParser from ogn.parser.aprs_comment.fanet_parser import FanetParser @@ -34,9 +33,12 @@ def parse(aprs_message, reference_timestamp=None, calculate_relations=False, use message = parse_aprs(aprs_message, reference_timestamp=reference_timestamp) if message['aprs_type'] == 'position' or message['aprs_type'] == 'status': - message.update(parse_comment(message['comment'], - dstcall=message['dstcall'], - aprs_type=message['aprs_type'])) + try: + message.update(parse_comment(message['comment'], + dstcall=message['dstcall'], + aprs_type=message['aprs_type'])) + except Exception: + raise OgnParseError(f"dstcall: {message['dstcall']}, aprs_type: {message['aprs_type']}, comment: {message['comment']}") if message['aprs_type'].startswith('position') and calculate_relations is True: positions[message['name']] = (message['longitude'], message['latitude']) @@ -60,7 +62,7 @@ def parse_aprs(message, reference_timestamp=None): 'reference_timestamp': reference_timestamp} if message and message[0] == '#': - match_server = re.search(PATTERN_SERVER, message) + match_server = PATTERN_SERVER.search(message) if match_server: result.update({ 'version': match_server.group('version'), @@ -74,13 +76,13 @@ def parse_aprs(message, reference_timestamp=None): 'comment': message, 'aprs_type': 'comment'}) else: - match = re.search(PATTERN_APRS, message) + match = PATTERN_APRS.search(message) if match: aprs_type = 'position' if match.group('aprs_type') == '/' else 'status' if match.group('aprs_type') == '>' else 'unknown' result.update({'aprs_type': aprs_type}) aprs_body = match.group('aprs_body') if aprs_type == 'position': - match_position = re.search(PATTERN_APRS_POSITION, aprs_body) + match_position = PATTERN_APRS_POSITION.search(aprs_body) if match_position: result.update({ 'name': match.group('callsign'), @@ -103,7 +105,7 @@ def parse_aprs(message, reference_timestamp=None): }) return result - match_position_weather = re.search(PATTERN_APRS_POSITION_WEATHER, aprs_body) + match_position_weather = PATTERN_APRS_POSITION_WEATHER.search(aprs_body) if match_position_weather: result.update({ 'aprs_type': 'position_weather', @@ -135,7 +137,7 @@ def parse_aprs(message, reference_timestamp=None): raise AprsParseError(message) elif aprs_type == 'status': - match_status = re.search(PATTERN_APRS_STATUS, aprs_body) + match_status = PATTERN_APRS_STATUS.search(aprs_body) if match_status: result.update({ 'name': match.group('callsign'), diff --git a/tests/parser/test_parse.py b/tests/parser/test_parse.py index a29fdf2..b161de9 100644 --- a/tests/parser/test_parse.py +++ b/tests/parser/test_parse.py @@ -6,7 +6,7 @@ from datetime import datetime from time import sleep from ogn.parser.parse import parse -from ogn.parser.exceptions import AprsParseError +from ogn.parser.exceptions import AprsParseError, OgnParseError class TestStringMethods(unittest.TestCase): @@ -114,6 +114,10 @@ class TestStringMethods(unittest.TestCase): self.assertEqual(message['name'], 'FLRDDA5BA') self.assertEqual(message['address'], 'DDA5BA') + def test_bad_naviter_format(self): + with self.assertRaises(OgnParseError): + parse("FLRA51D93>OGNAVI,qAS,NAVITER2:/204507h4444.98N/09323.34W'000/000/A=000925 !W67! id06A51D93 +000fpm +0.0rot") + if __name__ == '__main__': unittest.main()