From 895a1b60acb720cd64c3fe61c3e96d5f6943f79e Mon Sep 17 00:00:00 2001 From: Valery Date: Thu, 14 Mar 2024 08:38:08 +0300 Subject: [PATCH] weather message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pattern for weather message. Target message example: XUDN>WX,TCPIP,qAS,R8LAY-13:;XUDN *131019z5657.96N/04104.25E_236/007c236s007g013t029h89b10270Weather:overcast clouds; Cloudiness:99%; Wind:236° 3.1 m/s (5.8 m/s); Temp:-1.6°C; Humidity:89%; Dew point:-3.2°C; Pressure:1027 hPa; Visibility:10 km; Daylight:[11:38][06:36-18:14] --- ogn/parser/parse.py | 55 +++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/ogn/parser/parse.py b/ogn/parser/parse.py index 5e86271..23079af 100644 --- a/ogn/parser/parse.py +++ b/ogn/parser/parse.py @@ -2,7 +2,7 @@ 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.pattern import PATTERN_APRS, PATTERN_APRS_POSITION, PATTERN_APRS_POSITION_WEATHER, PATTERN_APRS_POSITION_WEATHER_WX, PATTERN_APRS_STATUS, PATTERN_SERVER from ogn.parser.exceptions import AprsParseError from ogn.parser.aprs_comment.ogn_parser import OgnParser @@ -20,19 +20,15 @@ from ogn.parser.aprs_comment.safesky_parser import SafeskyParser from ogn.parser.aprs_comment.generic_parser import GenericParser positions = {} -server_timestamp = None -def parse(aprs_message, reference_timestamp=None, calculate_relations=False, use_server_timestamp=True): +def parse(aprs_message, reference_timestamp=None, calculate_relations=False): global positions - global server_timestamp - if use_server_timestamp is True: - reference_timestamp = server_timestamp or datetime.utcnow() - elif reference_timestamp is None: + if reference_timestamp is None: reference_timestamp = datetime.utcnow() - message = parse_aprs(aprs_message, reference_timestamp=reference_timestamp) + message = parse_aprs(aprs_message, reference_timestamp) if message['aprs_type'] == 'position' or message['aprs_type'] == 'status': message.update(parse_comment(message['comment'], dstcall=message['dstcall'], @@ -46,9 +42,6 @@ def parse(aprs_message, reference_timestamp=None, calculate_relations=False, use message['bearing'] = cheap_ruler.bearing((message['longitude'], message['latitude']), positions[message['receiver_name']]) message['normalized_quality'] = normalized_quality(message['distance'], message['signal_quality']) if 'signal_quality' in message else None - if message['aprs_type'] == 'server': - server_timestamp = message['timestamp'] - return message @@ -76,13 +69,14 @@ def parse_aprs(message, reference_timestamp=None): else: match = re.search(PATTERN_APRS, 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}) + result.update({'aprs_type': 'unknown'}) + aprs_type = 'position' if match.group('aprs_type') == '/' else 'status' if match.group('aprs_type') == '>' else 'weather_wx' if match.group('aprs_type') == ';' else 'unknown' aprs_body = match.group('aprs_body') if aprs_type == 'position': match_position = re.search(PATTERN_APRS_POSITION, aprs_body) if match_position: result.update({ + 'aprs_type': 'position', 'name': match.group('callsign'), 'dstcall': match.group('dstcall'), 'relay': match.group('relay') if match.group('relay') else None, @@ -132,12 +126,12 @@ def parse_aprs(message, reference_timestamp=None): 'comment': match_position_weather.group('comment') if match_position_weather.group('comment') else "", }) return result - raise AprsParseError(message) elif aprs_type == 'status': match_status = re.search(PATTERN_APRS_STATUS, aprs_body) if match_status: result.update({ + 'aprs_type': 'status', 'name': match.group('callsign'), 'dstcall': match.group('dstcall'), 'receiver_name': match.group('receiver'), @@ -145,6 +139,37 @@ def parse_aprs(message, reference_timestamp=None): 'comment': match_status.group('comment') if match_status.group('comment') else ""}) else: raise NotImplementedError(message) + elif aprs_type == 'weather_wx': + match_position_weather = re.search(PATTERN_APRS_POSITION_WEATHER_WX, aprs_body) + if match_position_weather: + result.update({ + 'aprs_type': 'position_weather', + + 'name': match_position_weather.group('callsign').strip(), + 'dstcall': match.group('dstcall'), + 'relay': match.group('relay') if match.group('relay') else None, + 'receiver_name': match.group('receiver'), + 'timestamp': createTimestamp(match_position_weather.group('time'), reference_timestamp), + 'latitude': parseAngle('0' + match_position_weather.group('latitude')) * # noqa: W504 + (-1 if match_position_weather.group('latitude_sign') == 'S' else 1), + 'symboltable': match_position_weather.group('symbol_table'), + 'longitude': parseAngle(match_position_weather.group('longitude')) * # noqa: W504 + (-1 if match_position_weather.group('longitude_sign') == 'W' else 1), + 'symbolcode': match_position_weather.group('symbol'), + + 'wind_direction': int(match_position_weather.group('wind_direction')) if match_position_weather.group('wind_direction') != None else None, + 'wind_speed': int(match_position_weather.group('wind_speed')) * KNOTS_TO_MS / KPH_TO_MS if match_position_weather.group('wind_speed') != None else None, + 'wind_speed_peak': int(match_position_weather.group('wind_speed_peak')) * KNOTS_TO_MS / KPH_TO_MS if match_position_weather.group('wind_speed_peak') != None else None, + 'temperature': fahrenheit_to_celsius(float(match_position_weather.group('temperature'))) if match_position_weather.group('temperature') != None else None, + 'rainfall_1h': int(match_position_weather.group('rainfall_1h')) / 100.0 * INCH_TO_MM if match_position_weather.group('rainfall_1h') else None, + 'rainfall_24h': int(match_position_weather.group('rainfall_24h')) / 100.0 * INCH_TO_MM if match_position_weather.group('rainfall_24h') else None, + 'humidity': int(match_position_weather.group('humidity')) * 0.01 if match_position_weather.group('humidity') else None, + 'barometric_pressure': int(match_position_weather.group('barometric_pressure'))/10 if match_position_weather.group('barometric_pressure') else None, + + 'comment': match_position_weather.group('comment') if match_position_weather.group('comment') else "", + }) + + return result else: raise AprsParseError(message) @@ -171,6 +196,8 @@ dstcall_parser_mapping = {'APRS': OgnParser(), def parse_comment(aprs_comment, dstcall='APRS', aprs_type="position"): + print('parse_comment') + print(aprs_comment) parser = dstcall_parser_mapping.get(dstcall) if parser: return parser.parse(aprs_comment, aprs_type)