From cd3724696d5b6fe31829f2fadcc9ee12de503d2a Mon Sep 17 00:00:00 2001 From: ua1zbe Date: Fri, 24 Mar 2023 15:55:32 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=B8?= =?UTF-8?q?=D0=BB(=D0=B0)=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B2=20'apr?= =?UTF-8?q?slib/parsing'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aprslib/parsing/weather.py | 79 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 aprslib/parsing/weather.py diff --git a/aprslib/parsing/weather.py b/aprslib/parsing/weather.py new file mode 100644 index 0000000..010198b --- /dev/null +++ b/aprslib/parsing/weather.py @@ -0,0 +1,79 @@ +import re +from aprslib.exceptions import ParseError + +__all__ = [ + 'parse_weather', + 'parse_weather_data', + ] + +# constants +wind_multiplier = 0.44704 +rain_multiplier = 0.254 + +key_map = { + 'g': 'wind_gust', + 'c': 'wind_direction', + 't': 'temperature', + 's': 'wind_speed', + 'r': 'rain_1h', + 'p': 'rain_24h', + 'P': 'rain_since_midnight', + 'h': 'humidity', + 'b': 'pressure', + 'l': 'luminosity', + 'L': 'luminosity', + 'S': 'snow', + '#': 'rain_raw', +} +val_map = { + 'g': lambda x: int(x) * wind_multiplier, + 'c': lambda x: int(x), + 's': lambda x: int(x) * wind_multiplier, + 't': lambda x: (float(x) - 32) / 1.8, + 'r': lambda x: int(x) * rain_multiplier, + 'p': lambda x: int(x) * rain_multiplier, + 'P': lambda x: int(x) * rain_multiplier, + 'h': lambda x: 100 if int(x) == 0 else int(x), + 'b': lambda x: float(x) / 10, + 'l': lambda x: int(x) + 1000, + 'L': lambda x: int(x), + 'S': lambda x: float(x) * 25.4, + '#': lambda x: int(x), +} + +def parse_weather_data(body): + parsed = {} + + # parse weather data + body = re.sub(r"^([0-9]{3})/([0-9]{3})", "c\\1s\\2", body) + #body = body.replace('s', 'S', 1) + + # match as many parameters from the start, rest is comment + data = re.match(r"^([csgtrpPlLS#][0-9\-\. ]{3}|h[0-9\. ]{2}|b[0-9\. ]{5})+", body) + + if data: + data = data.group() + # split out data from comment + body = body[len(data):] + # parse all weather parameters + data = re.findall(r"([csgtrpPlLS#]\d{3}|t-\d{2}|h\d{2}|b\d{5}|s\.\d{2}|s\d\.\d)", data) + data = map(lambda x: (key_map[x[0]] , val_map[x[0]](x[1:])), data) + parsed.update(dict(data)) + + return (body, parsed) + +def parse_weather(body): + match = re.match(r"^(\d{8})c[\. \d]{3}s[\. \d]{3}g[\. \d]{3}t[\. \d]{3}", body) + if not match: + raise ParseError("invalid positionless weather report format") + + comment, weather = parse_weather_data(body[8:]) + + parsed = { + 'format': 'wx', + 'wx_raw_timestamp': match.group(1), + 'comment': comment.strip(' '), + 'weather': weather, + } + + return ('', parsed)