def test_metar(self): """ Tests converting METAR data into into a single spoken string """ units = structs.Units(**static.NA_UNITS) data = { 'altimeter': core.make_number('2992'), 'clouds': [core.make_cloud('BKN015CB')], 'dewpoint': core.make_number('M01'), 'other': ['+RA'], 'temperature': core.make_number('03'), 'visibility': core.make_number('3'), 'wind_direction': core.make_number('360'), 'wind_gust': core.make_number('20'), 'wind_speed': core.make_number('12'), 'wind_variable_direction': [ core.make_number('340'), core.make_number('020', speak='020') ] } data.update({k: None for k in ( 'raw', 'remarks', 'station', 'time', 'flight_rules', 'remarks_info', 'runway_visibility', 'sanitized' )}) data = structs.MetarData(**data) spoken = ('Winds three six zero (variable three four zero to zero two zero) ' 'at 12kt gusting to 20kt. Visibility three miles. ' 'Temperature three degrees Celsius. Dew point minus one degree Celsius. ' 'Altimeter two nine point nine two. Heavy Rain. ' 'Broken layer at 1500ft (Cumulonimbus)') ret = speech.metar(data, units) self.assertIsInstance(ret, str) self.assertEqual(ret, spoken)
def test_taf(self): """ Tests end-to-end TAF translation """ units = structs.Units(**static.core.NA_UNITS) line_data = { "altimeter": core.make_number("29.92", "2992"), "clouds": [core.make_cloud("BKN015CB")], "icing": ["611005"], "other": [], "turbulence": ["540553"], "visibility": core.make_number("3"), "wind_direction": core.make_number("360"), "wind_gust": core.make_number("20"), "wind_shear": "WS020/07040KT", "wind_speed": core.make_number("12"), "wx_codes": get_wx_codes(["+RA"])[1], } line_data.update({ k: "" for k in ( "raw", "end_time", "start_time", "transition_start", "probability", "type", "flight_rules", "sanitized", ) }) data = {"max_temp": "TX20/1518Z", "min_temp": "TN00/00", "remarks": ""} data.update({ k: "" for k in ("raw", "station", "time", "start_time", "end_time") }) data = structs.TafData(forecast=[structs.TafLineData(**line_data)], **data) line_trans = structs.TafLineTrans( altimeter="29.92 inHg (1013 hPa)", clouds="Broken layer at 1500ft (Cumulonimbus) - Reported AGL", icing="Light icing from 10000ft to 15000ft", turbulence= "Occasional moderate turbulence in clouds from 5500ft to 8500ft", visibility="3sm (4.8km)", wind_shear="Wind shear 2000ft from 070 at 40kt", wind="N-360 at 12kt gusting to 20kt", wx_codes="Heavy Rain", ) trans = structs.TafTrans( forecast=[line_trans], max_temp="Maximum temperature of 20°C (68°F) at 15-18:00Z", min_temp="Minimum temperature of 0°C (32°F) at 00:00Z", remarks={}, ) translated = translate.taf.translate_taf(data, units) self.assertIsInstance(translated, structs.TafTrans) for line in translated.forecast: self.assertIsInstance(line, structs.TafLineTrans) self.assertEqual(translated, trans)
def test_taf_line(self): """ Tests converting TAF line data into into a single spoken string """ units = structs.Units(**static.NA_UNITS) line = { 'altimeter': core.make_number('2992'), 'clouds': [core.make_cloud('BKN015CB')], 'end_time': core.make_timestamp('1206'), 'icing': ['611005'], 'other': ['+RA'], 'start_time': core.make_timestamp('1202'), 'turbulance': ['540553'], 'type': 'FROM', 'visibility': core.make_number('3'), 'wind_direction': core.make_number('360'), 'wind_gust': core.make_number('20'), 'wind_shear': 'WS020/07040KT', 'wind_speed': core.make_number('12'), } line.update({ k: None for k in ('flight_rules', 'probability', 'raw', 'sanitized') }) line = structs.TafLineData(**line) spoken = ( 'From 2 to 6 zulu, Winds three six zero at 12kt gusting to 20kt. ' 'Wind shear 2000inHg from zero seven zero at 40kt. Visibility three miles. ' 'Altimeter two nine point nine two. Heavy Rain. ' 'Broken layer at 1500ft (Cumulonimbus). ' 'Occasional moderate turbulence in clouds from 5500ft to 8500ft. ' 'Light icing from 10000ft to 15000ft') ret = speech.taf_line(line, units) self.assertIsInstance(ret, str) self.assertEqual(ret, spoken)
def test_get_wind(self): """ Tests that the wind item gets removed and split into its components """ # Both us knots as the default unit, so just test North American default for wx, unit, *wind, varv in ( (["1"], "kt", (None, ), (None, ), (None, ), []), (["12345(E)", "G50", "1"], "kt", ("123", 123), ("45", 45), ("50", 50), []), (["O1234G56", "1"], "kt", ("012", 12), ("34", 34), ("56", 56), []), ( ["36010KTS", "G20", "300V060", "1"], "kt", ("360", 360), ("10", 10), ("20", 20), [("300", 300), ("060", 60)], ), (["VRB10MPS", "1"], "m/s", ("VRB", ), ("10", 10), (None, ), []), (["VRB20G30KMH", "1"], "km/h", ("VRB", ), ("20", 20), ("30", 30), []), ): units = structs.Units(**static.NA_UNITS) wx, *winds, var = _core.get_wind(wx, units) self.assertEqual(wx, ["1"]) for i in range(len(wind)): self.assert_number(winds[i], *wind[i]) if varv: self.assertIsInstance(varv, list) for i in range(2): self.assert_number(var[i], *varv[i]) self.assertEqual(units.wind_speed, unit)
def test_get_wind(self): """ Tests that the wind item gets removed and split into its components """ #Both us knots as the default unit, so just test North American default for wx, unit, *wind, varv in ((['1' ], 'kt', (None, ), (None, ), (None, ), []), (['12345(E)', 'G50', '1'], 'kt', ('123', 123), ('45', 45), ('50', 50), []), (['O1234G56', '1'], 'kt', ('012', 12), ('34', 34), ('56', 56), []), (['36010KTS', 'G20', '300V060', '1'], 'kt', ('360', 360), ('10', 10), ('20', 20), [ ('300', 300), ('060', 60) ]), (['VRB10MPS', '1'], 'm/s', ('VRB', ), ('10', 10), (None, ), []), (['VRB20G30KMH', '1'], 'km/h', ('VRB', ), ('20', 20), ('30', 30), [])): units = structs.Units(**static.NA_UNITS) wx, *winds, var = _core.get_wind(wx, units) self.assertEqual(wx, ['1']) for i in range(len(wind)): self.assert_number(winds[i], *wind[i]) if varv: self.assertIsInstance(varv, list) for i in range(2): self.assert_number(var[i], *varv[i]) self.assertEqual(units.wind_speed, unit)
def test_taf_line(self): """ Tests converting TAF line data into into a single spoken string """ units = structs.Units(**static.NA_UNITS) line = { "altimeter": _core.make_number("2992"), "clouds": [_core.make_cloud("BKN015CB")], "end_time": _core.make_timestamp("1206"), "icing": ["611005"], "other": ["+RA"], "start_time": _core.make_timestamp("1202"), "turbulence": ["540553"], "type": "FROM", "visibility": _core.make_number("3"), "wind_direction": _core.make_number("360"), "wind_gust": _core.make_number("20"), "wind_shear": "WS020/07040KT", "wind_speed": _core.make_number("12"), } line.update( {k: None for k in ("flight_rules", "probability", "raw", "sanitized")} ) line = structs.TafLineData(**line) spoken = ( "From 2 to 6 zulu, Winds three six zero at 12kt gusting to 20kt. " "Wind shear 2000inHg from zero seven zero at 40kt. Visibility three miles. " "Altimeter two nine point nine two. Heavy Rain. " "Broken layer at 1500ft (Cumulonimbus). " "Occasional moderate turbulence in clouds from 5500ft to 8500ft. " "Light icing from 10000ft to 15000ft" ) ret = speech.taf_line(line, units) self.assertIsInstance(ret, str) self.assertEqual(ret, spoken)
def test_get_altimeter(self): """Tests that the correct alimeter item gets removed from the end of the wx list""" for version, wx, alt, unit in ( ("NA", ["1"], (None, ), "inHg"), ("NA", ["1", "A2992"], ("A2992", 29.92, "two nine point nine two"), "inHg"), ( "NA", ["1", "A3000"], ("A3000", 30.00, "three zero point zero zero"), "inHg", ), ("NA", ["1", "2992"], ("2992", 29.92, "two nine point nine two"), "inHg"), ( "NA", ["1", "A2992", "Q1000"], ("A2992", 29.92, "two nine point nine two"), "inHg", ), ( "NA", ["1", "Q1000", "A2992"], ("A2992", 29.92, "two nine point nine two"), "inHg", ), ("NA", ["1", "Q1000"], ("Q1000", 1000, "one zero zero zero"), "hPa"), ("IN", ["1"], (None, ), "hPa"), ("IN", ["1", "Q.1000"], ("Q.1000", 1000, "one zero zero zero"), "hPa"), ("IN", ["1", "Q1000/10"], ("Q1000/10", 1000, "one zero zero zero"), "hPa"), ( "IN", ["1", "A2992", "Q1000"], ("Q1000", 1000, "one zero zero zero"), "hPa", ), ( "IN", ["1", "Q1000", "A2992"], ("Q1000", 1000, "one zero zero zero"), "hPa", ), ("IN", ["1", "A2992"], ("A2992", 29.92, "two nine point nine two"), "inHg"), ( "IN", ["1", "QNH3003INS"], ("QNH3003INS", 30.03, "three zero point zero three"), "inHg", ), ): units = structs.Units(**getattr(static.core, version + "_UNITS")) ret, ret_alt = metar.get_altimeter(wx, units, version) self.assertEqual(ret, ["1"]) self.assert_number(ret_alt, *alt) self.assertEqual(units.altimeter, unit)
def test_metar(self): """ Tests end-to-end METAR translation """ units = structs.Units(**static.core.NA_UNITS) data = { "altimeter": core.make_number("29.92", "2992"), "clouds": [core.make_cloud("BKN015CB")], "dewpoint": core.make_number("M01"), "other": [], "temperature": core.make_number("03"), "visibility": core.make_number("3"), "wind_direction": core.make_number("360"), "wind_gust": core.make_number("20"), "wind_speed": core.make_number("12"), "wind_variable_direction": [ core.make_number("340"), core.make_number("020"), ], "wx_codes": get_wx_codes(["+RA"])[1], } data.update({ k: "" for k in ( "raw", "remarks", "station", "time", "flight_rules", "remarks_info", "runway_visibility", "sanitized", ) }) data = structs.MetarData(**data) trans = structs.MetarTrans( altimeter="29.92 inHg (1013 hPa)", clouds="Broken layer at 1500ft (Cumulonimbus) - Reported AGL", dewpoint="-1°C (30°F)", remarks={}, temperature="3°C (37°F)", visibility="3sm (4.8km)", wind="N-360 (variable 340 to 020) at 12kt gusting to 20kt", wx_codes="Heavy Rain", ) translated = translate.metar.translate_metar(data, units) self.assertIsInstance(translated, structs.MetarTrans) self.assertEqual(translated, trans)
def test_metar(self): """ Tests converting METAR data into into a single spoken string """ units = structs.Units(**static.core.NA_UNITS) data = { "altimeter": parse_altimeter("2992"), "clouds": [core.make_cloud("BKN015CB")], "dewpoint": core.make_number("M01"), "other": [], "temperature": core.make_number("03"), "visibility": core.make_number("3"), "wind_direction": core.make_number("360"), "wind_gust": core.make_number("20"), "wind_speed": core.make_number("12"), "wind_variable_direction": [ core.make_number("340"), core.make_number("020", speak="020"), ], "wx_codes": get_wx_codes(["+RA"])[1], } data.update({ k: None for k in ( "raw", "remarks", "station", "time", "flight_rules", "remarks_info", "runway_visibility", "sanitized", ) }) data = structs.MetarData(**data) spoken = ( "Winds three six zero (variable three four zero to zero two zero) " "at 12kt gusting to 20kt. Visibility three miles. " "Temperature three degrees Celsius. Dew point minus one degree Celsius. " "Altimeter two nine point nine two. Heavy Rain. " "Broken layer at 1500ft (Cumulonimbus)") ret = speech.metar(data, units) self.assertIsInstance(ret, str) self.assertEqual(ret, spoken)
def test_taf(self): """ Tests converting a TafData report into a single spoken string """ units = structs.Units(**static.core.NA_UNITS) empty_line = { k: None for k in structs.TafLineData.__dataclass_fields__.keys() } forecast = [ structs.TafLineData(**{ **empty_line, **line }) for line in ( { "type": "FROM", "start_time": core.make_timestamp("0410Z"), "end_time": core.make_timestamp("0414Z"), "visibility": core.make_number("3"), "wind_direction": core.make_number("360"), "wind_gust": core.make_number("20"), "wind_speed": core.make_number("12"), }, { "type": "PROB", "probability": core.make_number("45"), "start_time": core.make_timestamp("0412Z"), "end_time": core.make_timestamp("0414Z"), "visibility": core.make_number("M1/4"), }, ) ] taf = structs.TafData( raw=None, remarks=None, station=None, time=None, forecast=forecast, start_time=core.make_timestamp("0410Z"), end_time=core.make_timestamp("0414Z"), ) ret = speech.taf(taf, units) spoken = ( f"Starting on {taf.start_time.dt.strftime('%B')} 4th - From 10 to 14 zulu, " "Winds three six zero at 12kt gusting to 20kt. Visibility three miles. " r"From 12 to 14 zulu, there's a 45% chance for Visibility " "less than one quarter of a mile") self.assertIsInstance(ret, str) self.assertEqual(ret, spoken)
def test_taf(self): """ Tests end-to-end TAF translation """ units = structs.Units(**static.NA_UNITS) line_data = { 'altimeter': core.make_number('2992'), 'clouds': [core.make_cloud('BKN015CB')], 'icing': ['611005'], 'other': ['+RA'], 'turbulance': ['540553'], 'visibility': core.make_number('3'), 'wind_direction': core.make_number('360'), 'wind_gust': core.make_number('20'), 'wind_shear': 'WS020/07040KT', 'wind_speed': core.make_number('12') } line_data.update({ k: '' for k in ('raw', 'end_time', 'start_time', 'probability', 'type', 'flight_rules', 'sanitized') }) data = {'max_temp': 'TX20/1518Z', 'min_temp': 'TN00/00', 'remarks': ''} data.update({ k: '' for k in ('raw', 'station', 'time', 'start_time', 'end_time') }) data = structs.TafData(forecast=[structs.TafLineData(**line_data)], **data) line_trans = structs.TafLineTrans( altimeter='29.92 inHg (1013 hPa)', clouds='Broken layer at 1500ft (Cumulonimbus) - Reported AGL', icing='Light icing from 10000ft to 15000ft', other='Heavy Rain', turbulance= 'Occasional moderate turbulence in clouds from 5500ft to 8500ft', visibility='3sm (4.8km)', wind_shear='Wind shear 2000ft from 070 at 40kt', wind='N-360 at 12kt gusting to 20kt') trans = structs.TafTrans( forecast=[line_trans], max_temp='Maximum temperature of 20°C (68°F) at 15-18:00Z', min_temp='Minimum temperature of 0°C (32°F) at 00:00Z', remarks={}) translated = translate.taf(data, units) self.assertIsInstance(translated, structs.TafTrans) for line in translated.forecast: self.assertIsInstance(line, structs.TafLineTrans) self.assertEqual(translated, trans)
def test_get_altimeter(self): """ Tests that the correct alimeter item gets removed from the end of the wx list """ # North American default units = structs.Units(**static.NA_UNITS) for wx, alt in ( (['1', '2'], (None, )), (['1', '2', 'A2992'], ('2992', 29.92)), (['1', '2', '2992'], ('2992', 29.92)), (['1', '2', 'A2992', 'Q1000'], ('2992', 29.92)), (['1', '2', 'Q1000', 'A2992'], ('2992', 29.92)), (['1', '2', 'Q1000'], ('1000', 1000)), ): self.assertEqual(units.altimeter, 'inHg') retwx, ret_alt = _core.get_altimeter(wx, units) self.assertEqual(retwx, ['1', '2']) self.assert_number(ret_alt, *alt) # The last one should have changed the unit self.assertEqual(units.altimeter, 'hPa') # International units = structs.Units(**static.IN_UNITS) for wx, alt in ( (['1', '2'], (None, )), (['1', '2', 'Q.1000'], ('1000', 1000)), (['1', '2', 'Q1000/10'], ('1000', 1000)), (['1', '2', 'A2992', 'Q1000'], ('1000', 1000)), (['1', '2', 'Q1000', 'A2992'], ('1000', 1000)), (['1', '2', 'A2992'], ('2992', 29.92)), ): self.assertEqual(units.altimeter, 'hPa') retwx, ret_alt = _core.get_altimeter(wx, units, 'IN') self.assertEqual(retwx, ['1', '2']) self.assert_number(ret_alt, *alt) # The last one should have changed the unit self.assertEqual(units.altimeter, 'inHg')
def test_get_altimeter(self): """ Tests that the correct alimeter item gets removed from the end of the wx list """ # North American default units = structs.Units(**static.NA_UNITS) for wx, alt in ( (["1", "2"], (None, )), (["1", "2", "A2992"], ("2992", 29.92)), (["1", "2", "2992"], ("2992", 29.92)), (["1", "2", "A2992", "Q1000"], ("2992", 29.92)), (["1", "2", "Q1000", "A2992"], ("2992", 29.92)), (["1", "2", "Q1000"], ("1000", 1000)), ): self.assertEqual(units.altimeter, "inHg") retwx, ret_alt = _core.get_altimeter(wx, units) self.assertEqual(retwx, ["1", "2"]) self.assert_number(ret_alt, *alt) # The last one should have changed the unit self.assertEqual(units.altimeter, "hPa") # International units = structs.Units(**static.IN_UNITS) for wx, alt in ( (["1", "2"], (None, )), (["1", "2", "Q.1000"], ("1000", 1000)), (["1", "2", "Q1000/10"], ("1000", 1000)), (["1", "2", "A2992", "Q1000"], ("1000", 1000)), (["1", "2", "Q1000", "A2992"], ("1000", 1000)), (["1", "2", "A2992"], ("2992", 29.92)), ): self.assertEqual(units.altimeter, "hPa") retwx, ret_alt = _core.get_altimeter(wx, units, "IN") self.assertEqual(retwx, ["1", "2"]) self.assert_number(ret_alt, *alt) # The last one should have changed the unit self.assertEqual(units.altimeter, "inHg")
def test_taf(self): """ Tests converting a TafData report into a single spoken string """ units = structs.Units(**static.NA_UNITS) empty_line = { k: None for k in structs.TafLineData.__dataclass_fields__.keys() } forecast = [ structs.TafLineData(**{ **empty_line, **line }) for line in ( { 'type': 'FROM', 'start_time': core.make_timestamp('0410Z'), 'end_time': core.make_timestamp('0414Z'), 'visibility': core.make_number('3'), 'wind_direction': core.make_number('360'), 'wind_gust': core.make_number('20'), 'wind_speed': core.make_number('12'), }, { 'type': 'PROB', 'probability': core.make_number('45'), 'start_time': core.make_timestamp('0412Z'), 'end_time': core.make_timestamp('0414Z'), 'visibility': core.make_number('M1/4'), }, ) ] taf = structs.TafData(raw=None, remarks=None, station=None, time=None, forecast=forecast, start_time=core.make_timestamp('0410Z'), end_time=core.make_timestamp('0414Z')) ret = speech.taf(taf, units) spoken = ( f"Starting on {taf.start_time.dt.strftime('%B')} 4th - From 10 to 14 zulu, " "Winds three six zero at 12kt gusting to 20kt. Visibility three miles. " r"From 12 to 14 zulu, there's a 45% chance for Visibility " "less than one quarter of a mile") self.assertIsInstance(ret, str) self.assertEqual(ret, spoken)
def test_metar(self): """ Tests end-to-end METAR translation """ units = structs.Units(**static.NA_UNITS) data = { 'altimeter': core.make_number('2992'), 'clouds': [core.make_cloud('BKN015CB')], 'dewpoint': core.make_number('M01'), 'other': ['+RA'], 'temperature': core.make_number('03'), 'visibility': core.make_number('3'), 'wind_direction': core.make_number('360'), 'wind_gust': core.make_number('20'), 'wind_speed': core.make_number('12'), 'wind_variable_direction': [core.make_number('340'), core.make_number('020')] } data.update({ k: '' for k in ('raw', 'remarks', 'station', 'time', 'flight_rules', 'remarks_info', 'runway_visibility', 'sanitized') }) data = structs.MetarData(**data) trans = structs.MetarTrans( altimeter='29.92 inHg (1013 hPa)', clouds='Broken layer at 1500ft (Cumulonimbus) - Reported AGL', dewpoint='-1°C (30°F)', other='Heavy Rain', remarks={}, temperature='3°C (37°F)', visibility='3sm (4.8km)', wind='N-360 (variable 340 to 020) at 12kt gusting to 20kt') translated = translate.metar(data, units) self.assertIsInstance(translated, structs.MetarTrans) self.assertEqual(translated, trans)
def test_shared(self): """ Tests availibility of shared values between the METAR and TAF translations """ units = structs.Units(**static.NA_UNITS) data = structs.SharedData(altimeter=core.make_number('2992'), clouds=[core.make_cloud('OVC060')], flight_rules='', other=['RA'], sanitized='', visibility=core.make_number('10'), wind_direction=core.make_number('0'), wind_gust=core.make_number('0'), wind_speed=core.make_number('0')) trans = translate.shared(data, units) self.assertIsInstance(trans, dict) for key in ('altimeter', 'clouds', 'other', 'visibility'): self.assertIn(key, trans) self.assertTrue(bool(trans[key]))
def test_shared(self): """Tests availability of shared values between the METAR and TAF translations""" units = structs.Units(**static.core.NA_UNITS) data = structs.SharedData( altimeter=core.make_number("2992"), clouds=[core.make_cloud("OVC060")], flight_rules="", other=[], sanitized="", visibility=core.make_number("10"), wind_direction=core.make_number("0"), wind_gust=core.make_number("0"), wind_speed=core.make_number("0"), wx_codes=get_wx_codes(["RA"])[1], ) trans = translate.base.current_shared(data, units) self.assertIsInstance(trans, dict) for key in ("altimeter", "clouds", "visibility", "wx_codes"): self.assertIn(key, trans) self.assertTrue(bool(trans[key]))
def test_get_visibility(self): """Tests that the visibility item(s) gets removed and cleaned""" for wx, unit, visibility in ( (["1"], "sm", (None, )), (["05SM", "1"], "sm", ("5", 5)), (["10SM", "1"], "sm", ("10", 10)), (["P6SM", "1"], "sm", ("P6", )), (["M1/4SM", "1"], "sm", ("M1/4", )), (["1/2SM", "1"], "sm", ("1/2", 0.5)), (["2", "1/2SM", "1"], "sm", ("5/2", 2.5)), (["1000", "1"], "m", ("1000", 1000)), (["1000E", "1"], "m", ("1000", 1000)), (["1000NDV", "1"], "m", ("1000", 1000)), (["M1000", "1"], "m", ("1000", 1000)), (["2KM", "1"], "m", ("2000", 2000)), (["15KM", "1"], "m", ("15000", 15000)), ): units = structs.Units(**static.core.NA_UNITS) wx, vis = core.get_visibility(wx, units) self.assertEqual(wx, ["1"]) self.assert_number(vis, *visibility) self.assertEqual(units.visibility, unit)
def test_get_visibility(self): """ Tests that the visibility item(s) gets removed and cleaned """ for wx, unit, visibility in ( (['1'], 'sm', (None, )), (['05SM', '1'], 'sm', ('5', 5)), (['10SM', '1'], 'sm', ('10', 10)), (['P6SM', '1'], 'sm', ('P6', )), (['M1/4SM', '1'], 'sm', ('M1/4', )), (['1/2SM', '1'], 'sm', ('1/2', 0.5)), (['2', '1/2SM', '1'], 'sm', ('5/2', 2.5)), (['1000', '1'], 'm', ('1000', 1000)), (['1000E', '1'], 'm', ('1000', 1000)), (['1000NDV', '1'], 'm', ('1000', 1000)), (['M1000', '1'], 'm', ('1000', 1000)), (['2KM', '1'], 'm', ('2000', 2000)), ): units = structs.Units(**static.NA_UNITS) wx, vis = _core.get_visibility(wx, units) self.assertEqual(wx, ['1']) self.assert_number(vis, *visibility) self.assertEqual(units.visibility, unit)
class Reports(object): """ Base class containing multiple reports """ #: UTC Datetime object when the report was last updated last_updated: datetime = None #: Provide basic station info if given at init station_info: Station = None raw: [str] = None data: [structs.ReportData] = None units: structs.Units = structs.Units(**static.NA_UNITS) def __init__(self, station: str = None, lat: float = None, lon: float = None): if station: station = Station.from_icao(station) self.station_info = station lat = station.latitude lon = station.longitude elif lat is None or lon is None: raise ValueError("No station or valid coordinates given") self.lat = lat self.lon = lon self.service = service.NOAA("aircraftreport") def _post_update(self): pass @staticmethod def _report_filter(reports: [str]) -> [str]: """ Applies any report filtering before updating raw_reports """ return reports def update(self, reports: [str] = None, disable_post: bool = False) -> bool: """ Updates raw_reports and data by fetch recent aircraft reports Can accept a list report strings to parse instead Returns True if new reports are available, else False """ if not reports: reports = self.service.fetch(lat=self.lat, lon=self.lon) if not reports: return False if isinstance(reports, str): reports = [reports] if reports == self.raw: return False self.raw = self._report_filter(reports) if not disable_post: self._post_update() return True async def async_update(self, disable_post: bool = False) -> bool: """ Async version of update """ reports = await self.service.async_fetch(lat=self.lat, lon=self.lon) if not reports or reports == self.raw: return False self.raw = reports if not disable_post: self._post_update() return True