def test_invalid_data(): """Test loading and parsing xml file with data that cannot be parsed.""" file = open('tests/xml/buienradar_invalid.xml', 'r') data = file.read() file.close() latitude = 51.50 longitude = 6.20 result = parse_data(data, None, latitude, longitude, usexml=True) print(result) assert(result[SUCCESS] is False) assert(result[MESSAGE] == 'Location data is invalid.') file = open('tests/xml/buienradar_invalidfc1.xml', 'r') data = file.read() file.close() latitude = 51.98 longitude = 4.10 result = parse_data(data, None, latitude, longitude, usexml=True) print(result) assert(result[SUCCESS] and # noqa: ignore=W504 result[MESSAGE] is None) # test missing maxtemp: assert(len(result[DATA][FORECAST]) == 5 and # noqa: ignore=W504 result[DATA][FORECAST][0][TEMPERATURE] == 0.0) # test missing maxgtemp and maxtempmax: assert(len(result[DATA][FORECAST]) == 5 and # noqa: ignore=W504 result[DATA][FORECAST][2][TEMPERATURE] == 0.0) # read xml with invalid ws coordinates file = open('tests/xml/buienradar_invalidws1.xml', 'r') data = file.read() file.close() # 'Meetstation Arcen' contains invalid gps info, # 'Meetstation Volkel' will be selected as alternative latitude = 51.50 longitude = 6.20 result = parse_data(data, None, latitude, longitude, usexml=True) print(result) assert(result[SUCCESS] and # noqa: ignore=W504 '(6375)' in result[DATA][STATIONNAME]) # 'Meetstation Arnhem' contains invalid gps info, # 'Meetstation De Bilt' will be selected as alternative latitude = 52.07 longitude = 5.88 result = parse_data(data, None, latitude, longitude, usexml=True) print(result) assert(result[SUCCESS] and '(6260)' in result[DATA][STATIONNAME]) # 'Meetstation Berkhout' contains invalid gps info, # 'Meetstation Wijdenes' will be selected as alternative latitude = 52.65 longitude = 4.98 result = parse_data(data, None, latitude, longitude, usexml=True) print(result) assert(result[SUCCESS] and '(6248)' in result[DATA][STATIONNAME])
def test_nows(): """Test loading and parsing invalid xml file; no weatherstation.""" file = open('tests/buienradar_nows.xml', 'r') data = file.read() file.close() result = parse_data(data, None) # test calling results in the loop close cleanly print(result) assert (result[SUCCESS] is False and result[MESSAGE] == 'No location selected.') file = open('tests/buienradar_nows2.xml', 'r') data = file.read() file.close() result = parse_data(data, None) # test calling results in the loop close cleanly print(result) assert (result[SUCCESS] is False and result[MESSAGE] == 'No location selected.') file = open('tests/buienradar_nows3.xml', 'r') data = file.read() file.close() result = parse_data(data, None) # test calling results in the loop close cleanly print(result) assert (result[SUCCESS] is False and result[MESSAGE] == 'No location selected.') file = open('tests/buienradar_nows4.xml', 'r') data = file.read() file.close() result = parse_data(data, None) # test calling results in the loop close cleanly print(result) assert (result[SUCCESS] is False and result[MESSAGE] == 'No location selected.') file = open('tests/buienradar_nows5.xml', 'r') data = file.read() file.close() result = parse_data(data, None) # test calling results in the loop close cleanly print(result) assert (result[SUCCESS] is False and result[MESSAGE] == 'No location selected.')
async def async_update(self, *_): """Update the data from buienradar.""" content = await self.get_data(JSON_FEED_URL) if content.get(SUCCESS) is not True: # unable to get the data self.load_error_count += 1 threshold_log( self.load_error_count, "Unable to retrieve json data from Buienradar (Msg: %s, status: %s)", content.get(MESSAGE), content.get(STATUS_CODE), ) # schedule new call await self.schedule_update(SCHEDULE_NOK) return self.load_error_count = 0 # rounding coordinates prevents unnecessary redirects/calls lat = self.coordinates[CONF_LATITUDE] lon = self.coordinates[CONF_LONGITUDE] rainurl = json_precipitation_forecast_url(lat, lon) raincontent = await self.get_data(rainurl) if raincontent.get(SUCCESS) is not True: self.rain_error_count += 1 # unable to get the data threshold_log( self.rain_error_count, "Unable to retrieve rain data from Buienradar (Msg: %s, status: %s)", raincontent.get(MESSAGE), raincontent.get(STATUS_CODE), ) # schedule new call await self.schedule_update(SCHEDULE_NOK) return self.rain_error_count = 0 result = parse_data( content.get(CONTENT), raincontent.get(CONTENT), self.coordinates[CONF_LATITUDE], self.coordinates[CONF_LONGITUDE], self.timeframe, False, ) _LOGGER.debug("Buienradar parsed data: %s", result) if result.get(SUCCESS) is not True: if int(datetime.now().strftime("%H")) > 0: _LOGGER.warning( "Unable to parse data from Buienradar. (Msg: %s)", result.get(MESSAGE), ) await self.schedule_update(SCHEDULE_NOK) return self.data = result.get(DATA) await self.update_devices() await self.schedule_update(SCHEDULE_OK)
def async_update(self, *_): """Update the data from buienradar.""" from buienradar.buienradar import (parse_data, CONTENT, DATA, MESSAGE, STATUS_CODE, SUCCESS) result = yield from self.get_data('http://xml.buienradar.nl') if result.get(SUCCESS, False) is False: result = yield from self.get_data('http://api.buienradar.nl') if result.get(SUCCESS): result = parse_data(result.get(CONTENT), latitude=self.coordinates[CONF_LATITUDE], longitude=self.coordinates[CONF_LONGITUDE]) if result.get(SUCCESS): self.data = result.get(DATA) yield from self.update_devices() yield from self.schedule_update(10) else: yield from self.schedule_update(2) else: # unable to get the data _LOGGER.warning("Unable to retrieve data from Buienradar." "(Msg: %s, status: %s,)", result.get(MESSAGE), result.get(STATUS_CODE),) # schedule new call yield from self.schedule_update(2)
def async_update(self, *_): """Update the data from buienradar.""" from buienradar.buienradar import (parse_data, CONTENT, DATA, MESSAGE, STATUS_CODE, SUCCESS) result = yield from self.get_data('http://xml.buienradar.nl') if result.get(SUCCESS, False) is False: result = yield from self.get_data('http://api.buienradar.nl') if result.get(SUCCESS): result = parse_data(result.get(CONTENT), latitude=self.coordinates[CONF_LATITUDE], longitude=self.coordinates[CONF_LONGITUDE]) if result.get(SUCCESS): self.data = result.get(DATA) yield from self.update_devices() yield from self.schedule_update(10) else: yield from self.schedule_update(2) else: # unable to get the data _LOGGER.warning( "Unable to retrieve data from Buienradar." "(Msg: %s, status: %s,)", result.get(MESSAGE), result.get(STATUS_CODE), ) # schedule new call yield from self.schedule_update(2)
async def async_update(self, *_): """Update the data from buienradar.""" from buienradar.buienradar import (parse_data, CONTENT, DATA, MESSAGE, STATUS_CODE, SUCCESS) content = await self.get_data('http://xml.buienradar.nl') if not content.get(SUCCESS, False): content = await self.get_data('http://api.buienradar.nl') if content.get(SUCCESS) is not True: # unable to get the data _LOGGER.warning( "Unable to retrieve xml data from Buienradar." "(Msg: %s, status: %s,)", content.get(MESSAGE), content.get(STATUS_CODE), ) # schedule new call await self.schedule_update(SCHEDULE_NOK) return # rounding coordinates prevents unnecessary redirects/calls rainurl = 'http://gadgets.buienradar.nl/data/raintext/?lat={}&lon={}' rainurl = rainurl.format(round(self.coordinates[CONF_LATITUDE], 2), round(self.coordinates[CONF_LONGITUDE], 2)) raincontent = await self.get_data(rainurl) if raincontent.get(SUCCESS) is not True: # unable to get the data _LOGGER.warning( "Unable to retrieve raindata from Buienradar." "(Msg: %s, status: %s,)", raincontent.get(MESSAGE), raincontent.get(STATUS_CODE), ) # schedule new call await self.schedule_update(SCHEDULE_NOK) return result = parse_data(content.get(CONTENT), raincontent.get(CONTENT), self.coordinates[CONF_LATITUDE], self.coordinates[CONF_LONGITUDE], self.timeframe) _LOGGER.debug("Buienradar parsed data: %s", result) if result.get(SUCCESS) is not True: if int(datetime.now().strftime('%H')) > 0: _LOGGER.warning( "Unable to parse data from Buienradar." "(Msg: %s)", result.get(MESSAGE), ) await self.schedule_update(SCHEDULE_NOK) return self.data = result.get(DATA) await self.update_devices() await self.schedule_update(SCHEDULE_OK)
async def async_update(self, *_): """Update the data from buienradar.""" from buienradar.buienradar import (parse_data, CONTENT, DATA, MESSAGE, STATUS_CODE, SUCCESS) content = await self.get_data('http://xml.buienradar.nl') if not content.get(SUCCESS, False): content = await self.get_data('http://api.buienradar.nl') if content.get(SUCCESS) is not True: # unable to get the data _LOGGER.warning("Unable to retrieve xml data from Buienradar." "(Msg: %s, status: %s,)", content.get(MESSAGE), content.get(STATUS_CODE),) # schedule new call await self.schedule_update(SCHEDULE_NOK) return # rounding coordinates prevents unnecessary redirects/calls rainurl = 'http://gadgets.buienradar.nl/data/raintext/?lat={}&lon={}' rainurl = rainurl.format( round(self.coordinates[CONF_LATITUDE], 2), round(self.coordinates[CONF_LONGITUDE], 2) ) raincontent = await self.get_data(rainurl) if raincontent.get(SUCCESS) is not True: # unable to get the data _LOGGER.warning("Unable to retrieve raindata from Buienradar." "(Msg: %s, status: %s,)", raincontent.get(MESSAGE), raincontent.get(STATUS_CODE),) # schedule new call await self.schedule_update(SCHEDULE_NOK) return result = parse_data(content.get(CONTENT), raincontent.get(CONTENT), self.coordinates[CONF_LATITUDE], self.coordinates[CONF_LONGITUDE], self.timeframe) _LOGGER.debug("Buienradar parsed data: %s", result) if result.get(SUCCESS) is not True: if int(datetime.now().strftime('%H')) > 0: _LOGGER.warning("Unable to parse data from Buienradar." "(Msg: %s)", result.get(MESSAGE),) await self.schedule_update(SCHEDULE_NOK) return self.data = result.get(DATA) await self.update_devices() await self.schedule_update(SCHEDULE_OK)
def test_parse_timeframe(): """Test loading and parsing xml file.""" data = None raindata = None latitude = 51.50 longitude = 6.20 try: result = parse_data(data, raindata, latitude, longitude, 4, usexml=True) # timeframe=4 should raise a ValueError, so: assert(False) except ValueError: # timeframe=4 should raise a ValueError, so: assert(True) try: result = parse_data(data, raindata, latitude, longitude, 5, usexml=True) # timeframe=5 should NOT raise a ValueError, so: assert(True and result[SUCCESS] is False) except ValueError: # timeframe=5 should NOT raise a ValueError, so: assert(False) try: result = parse_data(data, raindata, latitude, longitude, 121, usexml=True) # timeframe=121 should raise a ValueError, so: assert(False) except ValueError: # timeframe=121 should raise a ValueError, so: assert(True) try: result = parse_data(data, raindata, latitude, longitude, 120, usexml=True) # timeframe=120 should NOT raise a ValueError, so: assert(True and result[SUCCESS] is False) except ValueError: # timeframe=120 should NOT raise a ValueError, so: assert(False)
def test_nofc2(): """Test loading and parsing invalid xml file; no forecast.""" file = open('tests/buienradar_nofc2.xml', 'r') data = file.read() file.close() result = parse_data(data, None) # test calling results in the loop close cleanly print(result) assert (result[SUCCESS] and len(result[DATA][FORECAST]) == 0)
def test_nofc(): """Test loading and parsing invalid xml file: no forecast data.""" file = open('tests/buienradar_nofc.xml', 'r') data = file.read() file.close() result = parse_data(data, None) # test calling results in the loop close cleanly print(result) assert (result[SUCCESS] and result[MESSAGE] == 'Unable to extract forecast data.')
def test_noroot(): """Test loading and parsing invalid xml file.""" # load noxml_file file = open('tests/buienradar_noroot.xml', 'r') data = file.read() file.close() result = parse_data(data, None) # test calling results in the loop close cleanly print(result) assert (result[SUCCESS] is False and result[MESSAGE] == 'Unable to parse content as xml.')
def get_data(self, lat: Optional[float] = None, long: Optional[float] = None, time_frame: Optional[int] = None) \ -> Dict[str, Any]: # noinspection PyPackageRequirements from buienradar.buienradar import get_data, parse_data # noinspection PyPackageRequirements from buienradar.constants import SUCCESS, CONTENT, RAINCONTENT, DATA lat = lat or self.lat long = long or self.long time_frame = time_frame or self.time_frame result = get_data(latitude=lat, longitude=long) if not result.get(SUCCESS): raise RuntimeError('Error while retrieving data') data = result.get(CONTENT) rain_data = result.get(RAINCONTENT) result = parse_data(data, rain_data, lat, long, time_frame) return result.get(DATA, {})
def async_update(self, *_): """Update the data from buienradar.""" from buienradar.buienradar import (parse_data, CONTENT, DATA, MESSAGE, STATUS_CODE, SUCCESS) content = yield from self.get_data('http://xml.buienradar.nl') if not content.get(SUCCESS, False): content = yield from self.get_data('http://api.buienradar.nl') # rounding coordinates prevents unnecessary redirects/calls rainurl = 'http://gadgets.buienradar.nl/data/raintext/?lat={}&lon={}' rainurl = rainurl.format(round(self.coordinates[CONF_LATITUDE], 2), round(self.coordinates[CONF_LONGITUDE], 2)) raincontent = yield from self.get_data(rainurl) if content.get(SUCCESS) and raincontent.get(SUCCESS): result = parse_data(content.get(CONTENT), raincontent.get(CONTENT), self.coordinates[CONF_LATITUDE], self.coordinates[CONF_LONGITUDE], self.timeframe) if result.get(SUCCESS): self.data = result.get(DATA) yield from self.update_devices() yield from self.schedule_update(10) else: yield from self.schedule_update(2) else: # unable to get the data _LOGGER.warning( "Unable to retrieve data from Buienradar." "(Msg: %s, status: %s,)", result.get(MESSAGE), result.get(STATUS_CODE), ) # schedule new call yield from self.schedule_update(2)
def forecast(): timeframe = 60 raindata = 0 # gps-coordinates for the weather data latitude = float(request.args.get('latitude')) longitude = float(request.args.get('longitude')) result = get_data( latitude=latitude, longitude=longitude, ) if result.get(SUCCESS): data = result[CONTENT] raindata = result[RAINCONTENT] result = parse_data(data, raindata, latitude, longitude, timeframe) response = jsonify({ "forecast": result, "rainfall": parse_rainfall(raindata) }) response.headers.add('Access-Control-Allow-Origin', '*') return response
"""Example usage.""" from buienradar.buienradar import (CONTENT, RAINCONTENT, SUCCESS, get_data, parse_data) # minutes to look ahead for precipitation forecast # (5..120) timeframe = 60 # gps-coordinates for the weather data latitude = 51.50 longitude = 6.20 result = get_data( latitude=latitude, longitude=longitude, ) if result.get(SUCCESS): data = result[CONTENT] raindata = result[RAINCONTENT] result = parse_data(data, raindata, latitude, longitude, timeframe) print(result)
def test_missing_data(): """Test loading and parsing invalid xml file; missing data fields.""" file = open('tests/buienradar_missing.xml', 'r') data = file.read() file.close() latitude = 51.50 longitude = 6.20 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: stationnaam ") latitude = 52.07 longitude = 5.88 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: icoonactueel ") latitude = 52.65 longitude = 4.98 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: luchtvochtigheid ") latitude = 52.10 longitude = 5.18 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: temperatuurGC ") latitude = 52.92 longitude = 4.78 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: temperatuur10cm ") latitude = 51.45 longitude = 5.42 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: windsnelheidMS ") latitude = 51.20 longitude = 5.77 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: windsnelheidBF ") latitude = 52.00 longitude = 3.28 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: windrichtingGR ") latitude = 51.57 longitude = 4.93 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: windrichting ") latitude = 52.07 longitude = 6.65 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: luchtdruk ") latitude = 52.43 longitude = 6.27 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: windstotenMS ") latitude = 51.87 longitude = 5.15 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: regenMMPU ") latitude = 51.98 longitude = 4.10 result = parse_data(data, None, latitude, longitude) print(result) assert (result[SUCCESS] and result[MESSAGE] == "Missing key(s) in br data: zonintensiteitWM2 ")
def test_readdata3(): """Test loading and parsing xml file.""" # load buienradar.xml file = open('tests/buienradar.xml', 'r') data = file.read() file.close() # select last weather stationnaam # gps coordinates not exact, so non-zero distance # Meetstation Zeeplatform K13 (6252) latitude = 53.23 longitude = 3.23 result = parse_data(data, None, latitude, longitude) print(result) assert(result[SUCCESS] and result[MESSAGE] is None) # check the selected weatherstation: assert(result[SUCCESS] and '(6252)' in result[DATA][STATIONNAME]) # check the data: fc1 = (datetime.now(pytz.timezone(__TIMEZONE)) + timedelta(days=1)) fc2 = (datetime.now(pytz.timezone(__TIMEZONE)) + timedelta(days=2)) fc3 = (datetime.now(pytz.timezone(__TIMEZONE)) + timedelta(days=3)) fc4 = (datetime.now(pytz.timezone(__TIMEZONE)) + timedelta(days=4)) fc5 = (datetime.now(pytz.timezone(__TIMEZONE)) + timedelta(days=5)) fc1 = fc1.replace(hour=12, minute=0, second=0, microsecond=0) fc2 = fc2.replace(hour=12, minute=0, second=0, microsecond=0) fc3 = fc3.replace(hour=12, minute=0, second=0, microsecond=0) fc4 = fc4.replace(hour=12, minute=0, second=0, microsecond=0) fc5 = fc5.replace(hour=12, minute=0, second=0, microsecond=0) # '05/19/2017 00:20:00' loc_dt = datetime(2017, 5, 19, hour=0, minute=20, second=0, microsecond=0) measured = pytz.timezone(__TIMEZONE).localize(loc_dt) # Expected result: expect = { 'msg': None, 'success': True, 'distance': 1.297928, 'data': { 'attribution': 'Data provided by buienradar.nl', 'windspeed': 8.16, 'windazimuth': 59, 'groundtemperature': 0.0, 'windforce': 5, 'precipitation': 0.0, 'precipitation_forecast': None, 'humidity': 47, 'pressure': 1004.95, 'condition': {'condcode': 'c', 'condition': 'cloudy', 'detailed': 'cloudy', 'exact': 'Heavily clouded', 'exact_nl': 'Zwaar bewolkt', 'image': get_imageurl('cc')}, 'measured': measured, 'winddirection': 'O', 'stationname': 'Zeeplatform K13 (6252)', 'temperature': 16.8, 'visibility': 6200, 'irradiance': 614, 'windgust': 14.0, 'forecast': [ {'datetime': fc1, 'temperature': 16.0, 'maxtemp': 16.0, 'mintemp': 8.0, 'rainchance': 15, 'sunchance': 0, 'rain': 0.0, 'snow': 0.0, 'windforce': 3, 'condition': {'condcode': 'j', 'condition': 'cloudy', 'detailed': 'partlycloudy', 'exact': 'Mix of clear and high clouds', 'exact_nl': ('Mix van opklaringen en hoge ' 'bewolking'), 'image': get_imageurl('j')}}, {'datetime': fc2, 'temperature': 17.0, 'maxtemp': 17.0, 'mintemp': 8.0, 'rainchance': 1, 'sunchance': 43, 'rain': 0.0, 'snow': 0.0, 'windforce': 3, 'condition': {'condcode': 'b', 'condition': 'cloudy', 'detailed': 'partlycloudy', 'exact': ('Mix of clear and medium or low ' 'clouds'), 'exact_nl': ('Mix van opklaringen en ' 'middelbare of lage ' 'bewolking'), 'image': get_imageurl('b')}}, {'datetime': fc3, 'temperature': 22.0, 'maxtemp': 22.0, 'mintemp': 10.0, 'rainchance': 3, 'sunchance': 0, 'rain': 0.0, 'snow': 0.0, 'windforce': 4, 'condition': {'condcode': 'r', 'condition': 'cloudy', 'detailed': 'partlycloudy', 'exact': '?? Partly cloudy ??', 'exact_nl': '?? Partly cloudy ??', 'image': get_imageurl('r')}}, {'datetime': fc4, 'temperature': 18.0, 'maxtemp': 18.0, 'mintemp': 11.0, 'rainchance': 43, 'sunchance': 0, 'rain': 1.8, 'snow': 0.0, 'windforce': 4, 'condition': {'condcode': 'm', 'condition': 'rainy', 'detailed': 'light-rain', 'exact': ('Heavily clouded with some ' 'light rain'), 'exact_nl': ('Zwaar bewolkt met wat lichte' ' regen'), 'image': get_imageurl('m')}}, {'datetime': fc5, 'temperature': 15.0, 'maxtemp': 15.0, 'mintemp': 9.0, 'rainchance': 76, 'sunchance': 0, 'rain': 4.4, 'snow': 0.0, 'windforce': 4, 'condition': {'condcode': 'f', 'condition': 'rainy', 'detailed': 'partlycloudy-light-rain', 'exact': ('Alternatingly cloudy with some ' 'light rain'), 'exact_nl': ('Afwisselend bewolkt met ' '(mogelijk) wat lichte ' 'regen'), 'image': get_imageurl('f')}} ] }, } assert(expect == result)