Exemplo n.º 1
0
    def process_data(self):
        try:
            self.log.info('Processing Metar data...')

            with open(os.path.join(os.path.dirname(__file__), 'metar/stations.json')) as in_file:
                icao = json.load(in_file)

            now = arrow.utcnow()
            hour = now.hour
            minute = now.minute

            if minute < 45:
                current_cycle = hour
            else:
                current_cycle = hour + 1 % 24

            stations = {}
            for cycle in (current_cycle-1, current_cycle):
                file = f'http://tgftp.nws.noaa.gov/data/observations/metar/cycles/{cycle:02d}Z.TXT'
                self.log.info(f"Processing '{file}' ...")

                request = requests.get(file, stream=True, timeout=(self.connect_timeout, self.read_timeout))
                for line in request.iter_lines():
                    if line:
                        data = line.decode('iso-8859-1')
                        try:
                            # Is this line a date with format "2017/05/12 23:55" ?
                            arrow.get(data, 'YYYY/MM/DD HH:mm')
                            continue
                            # Catch also ValueError because https://github.com/crsmithdev/arrow/issues/535
                        except (arrow.parser.ParserError, ValueError):
                            try:
                                metar = Metar(data, strict=False)
                                # wind_dir could be NONE if 'dir' is 'VRB'
                                if metar.wind_speed:
                                    if metar.station_id not in stations:
                                        stations[metar.station_id] = {}
                                    key = arrow.get(metar.time).timestamp
                                    stations[metar.station_id][key] = metar
                            except Exception as e:
                                self.log.warn(f'Error while parsing METAR data: {e}')
                                continue

            for metar_id in stations:
                metar = next(iter(stations[metar_id].values()))
                try:
                    name, short_name, default_name, lat, lon, altitude, tz = None, None, None, None, None, None, None

                    checkwx_key = f'metar/checkwx/{metar.station_id}'
                    if not self.redis.exists(checkwx_key):
                        try:
                            self.log.info('Calling api.checkwx.com...')
                            request = requests.get(
                                f'https://api.checkwx.com/station/{metar.station_id}',
                                headers={'Accept': 'application/json', 'X-API-Key': self.checkwx_api_key},
                                timeout=(self.connect_timeout, self.read_timeout)
                            )
                            if request.status_code == 401:
                                raise UsageLimitException(request.json()['errors'][0]['message'])
                            elif request.status_code == 429:
                                raise UsageLimitException('api.checkwx.com rate limit exceeded')

                            try:
                                checkwx_data = request.json()['data'][0]
                                if 'icao' not in checkwx_data:
                                    raise ProviderException('Invalid CheckWX data')
                            except (ValueError, KeyError):
                                checkwx_json = request.json()
                                messages = []
                                if type(checkwx_json['data']) is list:
                                    messages.extend(checkwx_json['data'])
                                else:
                                    messages.append(checkwx_json['data'])
                                raise ProviderException(f'CheckWX API error: {",".join(messages)}')

                            self.add_redis_key(checkwx_key, {
                                'data': json.dumps(checkwx_data),
                                'date': arrow.now().format('YYYY-MM-DD HH:mm:ssZZ'),
                            }, self.checkwx_cache_duration)
                        except TimeoutError as e:
                            raise e
                        except UsageLimitException as e:
                            self.add_redis_key(checkwx_key, {
                                'error': repr(e),
                                'date': arrow.now().format('YYYY-MM-DD HH:mm:ssZZ'),
                            }, self.usage_limit_cache_duration)
                        except Exception as e:
                            if not isinstance(e, ProviderException):
                                self.log.exception('Error while getting CheckWX data')
                            else:
                                self.log.warn(f'Error while getting CheckWX data: {e}')
                            self.add_redis_key(checkwx_key, {
                                'error': repr(e),
                                'date': arrow.now().format('YYYY-MM-DD HH:mm:ssZZ'),
                            }, self.checkwx_cache_duration)

                    if not self.redis.hexists(checkwx_key, 'error'):
                        checkwx_data = json.loads(self.redis.hget(checkwx_key, 'data'))

                        station_type = checkwx_data.get('type', None)
                        if station_type:
                            name = f'{checkwx_data["name"]} {station_type}'
                        else:
                            name = checkwx_data['name']
                        city = checkwx_data.get('city', None)
                        if city:
                            if station_type:
                                short_name = f'{city} {station_type}'
                            else:
                                short_name = city
                        else:
                            default_name = checkwx_data['name']

                        lat = checkwx_data['latitude']['decimal']
                        lon = checkwx_data['longitude']['decimal']
                        tz = checkwx_data['timezone']['tzid']
                        elevation = checkwx_data.get('elevation', None)
                        altitude = None
                        if elevation:
                            if 'meters' in elevation:
                                altitude = Q_(elevation['meters'], ureg.meters)
                            elif 'feet' in elevation:
                                altitude = Q_(elevation['feet'], ureg.feet)

                    if metar.station_id in icao:
                        lat = lat or icao[metar.station_id]['lat']
                        lon = lon or icao[metar.station_id]['lon']
                        default_name = default_name or icao[metar.station_id]['name']

                    station = self.save_station(
                        metar.station_id,
                        short_name,
                        name,
                        lat,
                        lon,
                        Status.GREEN,
                        altitude=altitude,
                        tz=tz,
                        url=os.path.join(self.provider_url, f'site?id={metar.station_id}&db=metar'),
                        default_name=default_name or f'{metar.station_id} Airport',
                        lookup_name=f'{metar.station_id} Airport ICAO')
                    station_id = station['_id']

                    if metar.station_id not in icao:
                        self.log.warn(f"Missing '{metar.station_id}' ICAO in database. Is it '{station['name']}'?")

                    measures_collection = self.measures_collection(station_id)
                    new_measures = []
                    for key in stations[metar_id]:
                        metar = stations[metar_id][key]
                        if not self.has_measure(measures_collection, key):
                            temp = self.get_quantity(metar.temp, self.temperature_units)
                            dew_point = self.get_quantity(metar.dewpt, self.temperature_units)
                            humidity = self.compute_humidity(dew_point, temp)
                            measure = self.create_measure(
                                station,
                                key,
                                self.get_direction(metar.wind_dir),
                                self.get_quantity(metar.wind_speed, self.speed_units),
                                self.get_quantity(metar.wind_gust or metar.wind_speed, self.speed_units),
                                temperature=temp,
                                humidity=humidity,
                                pressure=Pressure(qfe=None,
                                                  qnh=self.get_quantity(metar.press, self.pressure_units),
                                                  qff=self.get_quantity(metar.press_sea_level, self.pressure_units))
                            )
                            new_measures.append(measure)

                    self.insert_new_measures(measures_collection, station, new_measures)

                except ProviderException as e:
                    self.log.warn(f"Error while processing station '{metar_id}': {e}")
                except Exception as e:
                    self.log.exception(f"Error while processing station '{metar_id}': {e}")

        except Exception as e:
            self.log.exception(f'Error while processing Metar: {e}')

        self.log.info('Done !')
Exemplo n.º 2
0
    def process_data(self):
        try:
            self.log.info('Processing iWeathar data...')

            result_tree = etree.parse(
                requests.get(
                    f'https://iweathar.co.za/live_data.php?unit=kmh&key={self.iweathar_key}',
                    stream=True,
                    verify=False,
                    timeout=(self.connect_timeout, self.read_timeout)).raw)

            for item in result_tree.xpath('//ITEM'):
                station_id = None
                try:
                    iweathar_id = item.xpath('STATION_ID')[0].text
                    name = item.xpath('LOCATION')[0].text
                    status = Status.GREEN if item.xpath(
                        'STATUS')[0].text == 'ON-LINE' else Status.RED

                    station = self.save_station(
                        iweathar_id,
                        name,
                        name,
                        item.xpath('LAT')[0].text,
                        item.xpath('LONG')[0].text,
                        status,
                        url=f'{self.provider_url}/display?s_id={iweathar_id}')
                    station_id = station['_id']

                    key_attr = item.xpath('UNIX_DATE_STAMP')
                    wind_dir_attr = item.xpath('WIND_ANG')
                    wind_avg_attr = item.xpath('WIND_AVG')
                    wind_max_attr = item.xpath('WIND_MAX')
                    if not (key_attr and wind_dir_attr and wind_avg_attr
                            and wind_max_attr):
                        self.log.warning(
                            f"Station '{station_id}' has invalid data")
                        continue

                    key = int(key_attr[0].text)
                    measures_collection = self.measures_collection(station_id)
                    if not self.has_measure(measures_collection, key):
                        try:
                            temperature_attr = item.xpath('TEMPERATURE_C')
                            if temperature_attr and temperature_attr[0].text:
                                temperature = Q_(temperature_attr[0].text,
                                                 ureg.degC)
                            else:
                                temperature = None

                            humidity_attr = item.xpath('HUMIDITY_PERC')
                            if humidity_attr and humidity_attr[0].text:
                                humidity = humidity_attr[0].text
                            else:
                                humidity = None

                            pressure_attr = item.xpath('PRESSURE_MB')
                            if pressure_attr and pressure_attr[0].text:
                                pressure = Pressure(qfe=pressure_attr[0].text,
                                                    qnh=None,
                                                    qff=None)
                            else:
                                pressure = None

                            rain_attr = item.xpath('RAINFALL_MM')
                            if rain_attr and rain_attr[0].text:
                                rain = Q_(rain_attr[0].text,
                                          ureg.liter / (ureg.meter**2))
                            else:
                                rain = None

                            measure = self.create_measure(
                                station,
                                key,
                                wind_dir_attr[0].text,
                                wind_avg_attr[0].text,
                                wind_max_attr[0].text,
                                temperature=temperature,
                                humidity=humidity,
                                pressure=pressure,
                                rain=rain)
                            self.insert_new_measures(measures_collection,
                                                     station, [measure])
                        except ProviderException as e:
                            self.log.warning(
                                f"Error while processing measure '{key}' for station '{station_id}': {e}"
                            )
                        except Exception as e:
                            self.log.exception(
                                f"Error while processing measure '{key}' for station '{station_id}': {e}"
                            )

                except ProviderException as e:
                    self.log.warning(
                        f"Error while processing station '{station_id}': {e}")
                except Exception as e:
                    self.log.exception(
                        f"Error while processing station '{station_id}': {e}")

        except Exception as e:
            self.log.exception(f'Error while processing iWeathar: {e}')

        self.log.info('...Done!')
Exemplo n.º 3
0
    def process_data(self):
        try:
            self.log.info('Processing JDC data...')

            @retry(wait=wait_random_exponential(multiplier=2, min=2), stop=stop_after_delay(60),
                   after=after_log(self.log, logging.WARNING))
            def request_data():
                # jdc.ch randomly timeout early in the morning... backup tasks?
                return requests.get('http://meteo.jdc.ch/API/?Action=StationView&flags=all',
                                    timeout=(self.connect_timeout, self.read_timeout))

            result = request_data()

            try:
                jdc_stations = result.json()['Stations']
            except Exception:
                raise Exception('Action=StationView returns invalid json response')

            for jdc_station in jdc_stations:
                station_id = None
                try:
                    jdc_id = jdc_station['serial']
                    station = self.save_station(
                        jdc_id,
                        jdc_station['short-name'],
                        jdc_station['name'],
                        jdc_station['latitude'],
                        jdc_station['longitude'],
                        self.get_status(jdc_station['status']),
                        altitude=jdc_station['altitude'],
                        url=urllib.parse.urljoin(self.provider_url, '/station/' + str(jdc_station['serial'])))
                    station_id = station['_id']

                    try:
                        # Asking 2 days of data
                        result = requests.get(
                            f'http://meteo.jdc.ch/API/?Action=DataView&serial={jdc_id}&duration=172800',
                            timeout=(self.connect_timeout, self.read_timeout))
                        try:
                            json = result.json()
                        except ValueError:
                            raise Exception('Action=DataView returns invalid json response')
                        if json['ERROR'] == 'OK':
                            measures_collection = self.measures_collection(station_id)

                            measures = json['data']['measurements']
                            new_measures = []
                            for jdc_measure in measures:
                                key = jdc_measure['unix-time']
                                if not self.has_measure(measures_collection, key):
                                    try:
                                        measure = self.create_measure(
                                            station,
                                            key,
                                            jdc_measure.get('wind-direction'),
                                            jdc_measure.get('wind-average'),
                                            jdc_measure.get('wind-maximum'),
                                            temperature=jdc_measure.get('temperature'),
                                            humidity=jdc_measure.get('humidity'),
                                            pressure=Pressure(
                                                qfe=jdc_measure.get('pressure', None),
                                                qnh=None,
                                                qff=None),
                                            rain=jdc_measure.get('rain', None),
                                        )
                                        new_measures.append(measure)
                                    except ProviderException as e:
                                        self.log.warning(
                                            f"Error while processing measure '{key}' for station '{station_id}': {e}")
                                    except Exception as e:
                                        self.log.exception(
                                            f"Error while processing measure '{key}' for station '{station_id}': {e}")

                            self.insert_new_measures(measures_collection, station, new_measures)
                        else:
                            raise ProviderException(f"Action=Data returns an error: '{json['ERROR']}'")

                    except ProviderException as e:
                        self.log.warning(f"Error while processing measures for station '{station_id}': {e}")
                    except Exception as e:
                        self.log.exception(f"Error while processing measures for station '{station_id}': {e}")

                except ProviderException as e:
                    self.log.warning(f"Error while processing station '{station_id}': {e}")
                except Exception as e:
                    self.log.exception(f"Error while processing station '{station_id}': {e}")

        except Exception as e:
            self.log.exception(f'Error while processing JDC: {e}')

        self.log.info('Done !')
Exemplo n.º 4
0
    def process_data(self):
        try:
            self.log.info('Processing MeteoSwiss data...')

            base_url = 'https://www.meteoswiss.admin.ch'
            session = requests.Session()
            session.headers.update(user_agents.chrome)

            main_url = '/home/weather/measurement-values/measurement-values-at-meteorological-stations.html'
            html_tree = html.fromstring(
                session.get(base_url + main_url,
                            timeout=(self.connect_timeout,
                                     self.read_timeout)).text)

            # Main wind data
            element = html_tree.xpath(
                '//input[@id="measurement__param-radio--wind"]')[0]
            wind_datas = session.get(
                base_url + element.get('data-json-url'),
                timeout=(self.connect_timeout,
                         self.read_timeout)).json()['stations']

            # Temperature data
            element = html_tree.xpath(
                '//input[@id="measurement__param-radio--temperature"]')[0]
            temp_datas = session.get(
                base_url + element.get('data-json-url'),
                timeout=(self.connect_timeout,
                         self.read_timeout)).json()['stations']

            # Humidity data
            element = html_tree.xpath(
                '//input[@id="measurement__param-radio--humidity"]')[0]
            humidity_datas = session.get(
                base_url + element.get('data-json-url'),
                timeout=(self.connect_timeout,
                         self.read_timeout)).json()['stations']

            # Pressure data
            element = html_tree.xpath(
                '//option[@id="measurement__param-option--airpressure-qfe"]'
            )[0]
            pressure_datas_qfe = session.get(
                base_url + element.get('data-json-url'),
                timeout=(self.connect_timeout,
                         self.read_timeout)).json()['stations']

            element = html_tree.xpath(
                '//option[@id="measurement__param-option--airpressure-qnh"]'
            )[0]
            pressure_datas_qnh = session.get(
                base_url + element.get('data-json-url'),
                timeout=(self.connect_timeout,
                         self.read_timeout)).json()['stations']

            element = html_tree.xpath(
                '//option[@id="measurement__param-option--airpressure-qff"]'
            )[0]
            pressure_datas_qff = session.get(
                base_url + element.get('data-json-url'),
                timeout=(self.connect_timeout,
                         self.read_timeout)).json()['stations']

            # Rain data
            element = html_tree.xpath(
                '//input[@id="measurement__param-radio--precipitation"]')[0]
            rain_datas = session.get(
                base_url + element.get('data-json-url'),
                timeout=(self.connect_timeout,
                         self.read_timeout)).json()['stations']

            for wind_data in wind_datas:
                station_id = None
                try:
                    urls = {
                        lang: url.format(id=wind_data['id'].lower())
                        for lang, url in self.provider_urls.items()
                    }
                    station = self.save_station(
                        wind_data['id'],
                        wind_data['city_name'],
                        wind_data['city_name'],
                        ch_to_wgs_lat(int(wind_data['coord_x']),
                                      int(wind_data['coord_y'])),
                        ch_to_wgs_lon(int(wind_data['coord_x']),
                                      int(wind_data['coord_y'])),
                        Status.GREEN,
                        altitude=wind_data['evelation'],
                        tz='Europe/Zurich',
                        url=urls)
                    station_id = station['_id']

                    key = arrow.get(int(wind_data['date']) / 1000).timestamp

                    measures_collection = self.measures_collection(station_id)
                    new_measures = []

                    if not self.has_measure(measures_collection, key):
                        temp_data = None
                        for data in temp_datas:
                            if data['id'] == wind_data['id'] and data[
                                    'date'] == wind_data['date']:
                                temp_data = data

                        humidity_data = None
                        for data in humidity_datas:
                            if data['id'] == wind_data['id'] and data[
                                    'date'] == wind_data['date']:
                                humidity_data = data

                        pressure_data_qfe = None
                        for data in pressure_datas_qfe:
                            if data['id'] == wind_data['id'] and data[
                                    'date'] == wind_data['date']:
                                pressure_data_qfe = data

                        pressure_data_qnh = None
                        for data in pressure_datas_qnh:
                            if data['id'] == wind_data['id'] and data[
                                    'date'] == wind_data['date']:
                                pressure_data_qnh = data

                        pressure_data_qff = None
                        for data in pressure_datas_qff:
                            if data['id'] == wind_data['id'] and data[
                                    'date'] == wind_data['date']:
                                pressure_data_qff = data

                        rain_data = None
                        for data in rain_datas:
                            if data['id'] == wind_data['id'] and data[
                                    'date'] == wind_data['date']:
                                rain_data = data

                        wind_dir = None
                        if wind_data['current_value'][2] is not None:
                            wind_dir = Q_(wind_data['current_value'][2],
                                          ureg.degree)

                        wind_avg = None
                        if wind_data['current_value'][0] is not None:
                            wind_avg = Q_(wind_data['current_value'][0],
                                          ureg.kilometer / ureg.hour)

                        wind_max = None
                        if wind_data['current_value'][1] is not None:
                            wind_max = Q_(wind_data['current_value'][1],
                                          ureg.kilometer / ureg.hour)

                        temp = None
                        if temp_data and temp_data['current_value'] is not None:
                            temp = Q_(temp_data['current_value'], ureg.degC)

                        humidity = None
                        if humidity_data and humidity_data[
                                'current_value'] is not None:
                            humidity = humidity_data['current_value']

                        qfe = None
                        if pressure_data_qfe and pressure_data_qfe[
                                'current_value'] is not None:
                            qfe = Q_(pressure_data_qfe['current_value'],
                                     ureg.hPa)

                        qnh = None
                        if pressure_data_qnh and pressure_data_qnh[
                                'current_value'] is not None:
                            qnh = Q_(pressure_data_qnh['current_value'],
                                     ureg.hPa)

                        qff = None
                        if pressure_data_qff and pressure_data_qff[
                                'current_value'] is not None:
                            qff = Q_(pressure_data_qff['current_value'],
                                     ureg.hPa)

                        rain = None
                        if rain_data and rain_data['current_value'] is not None:
                            rain = Q_(rain_data['current_value'],
                                      ureg.liter / (ureg.meter**2))

                        measure = self.create_measure(
                            station,
                            key,
                            wind_dir,
                            wind_avg,
                            wind_max,
                            temperature=temp,
                            humidity=humidity,
                            pressure=Pressure(qfe=qfe, qnh=qnh, qff=qff),
                            rain=rain,
                        )
                        new_measures.append(measure)

                    self.insert_new_measures(measures_collection, station,
                                             new_measures)

                except ProviderException as e:
                    self.log.warn(
                        f"Error while processing station '{station_id}': {e}")
                except Exception as e:
                    self.log.exception(
                        f"Error while processing station '{station_id}': {e}")

        except Exception as e:
            self.log.exception(f'Error while processing MeteoSwiss: {e}')

        self.log.info('...Done!')
Exemplo n.º 5
0
    def process_data(self):
        try:
            self.log.info('Processing Romma data...')

            romma_tz = tz.gettz('Europe/Paris')

            result_tree = etree.fromstring(
                requests.get(
                    f'http://romma.fr/releves_romma_xml.php?id={self.romma_key}',
                    timeout=(self.connect_timeout, self.read_timeout)).text)

            for report in result_tree.xpath('//releves/releve'):
                station_id = None
                try:
                    romma_id = report.xpath('id')[0].text
                    name = report.xpath('station')[0].text
                    status = Status.GREEN if report.xpath(
                        'valide')[0].text == '1' else Status.RED

                    station = self.save_station(
                        romma_id,
                        name,
                        name,
                        report.xpath('latitude')[0].text,
                        report.xpath('longitude')[0].text,
                        status,
                        altitude=report.xpath('altitude')[0].text,
                        url=urllib.parse.urljoin(
                            self.provider_url,
                            f'/station_24.php?id={romma_id}'))
                    station_id = station['_id']

                    wind_dir = self.get_value(
                        report.xpath('direction')[0].text)
                    if not wind_dir:
                        self.log.warning(
                            f"Station '{station_id}' has no wind direction value"
                        )
                        continue

                    measures_collection = self.measures_collection(station_id)
                    key = arrow.get(
                        report.xpath('date')[0].text,
                        'D.MM.YYYY H:mm').replace(tzinfo=romma_tz).timestamp

                    if not self.has_measure(measures_collection, key):
                        try:
                            measure = self.create_measure(
                                station,
                                key,
                                self.wind_directions[wind_dir],
                                self.get_value(
                                    report.xpath('vent_moyen_10')[0].text),
                                self.get_value(
                                    report.xpath('rafale_maxi')[0].text),
                                temperature=self.get_value(
                                    report.xpath('temperature')[0].text),
                                humidity=self.get_value(
                                    report.xpath('humidite')[0].text),
                                pressure=Pressure(qfe=self.get_value(
                                    report.xpath('pression')[0].text),
                                                  qnh=None,
                                                  qff=None))
                            self.insert_new_measures(measures_collection,
                                                     station, [measure])
                        except ProviderException as e:
                            self.log.warning(
                                f"Error while processing measure '{key}' for station '{station_id}': {e}"
                            )
                        except Exception as e:
                            self.log.exception(
                                f"Error while processing measure '{key}' for station '{station_id}': {e}"
                            )

                except ProviderException as e:
                    self.log.warning(
                        f"Error while processing station '{station_id}': {e}")
                except Exception as e:
                    self.log.exception(
                        f"Error while processing station '{station_id}': {e}")

        except Exception as e:
            self.log.exception(f'Error while processing Romma: {e}')

        self.log.info('...Done!')
Exemplo n.º 6
0
    def process_data(self):
        stations = {}
        try:
            self.log.info('Processing FFVL data...')

            result = requests.get(
                'http://data.ffvl.fr/json/balises.json', timeout=(self.connect_timeout, self.read_timeout))
            ffvl_stations = result.json()

            for ffvl_station in ffvl_stations:
                ffvl_id = None
                try:
                    ffvl_id = ffvl_station['idBalise']
                    station = self.save_station(
                        ffvl_id,
                        ffvl_station['nom'],
                        ffvl_station['nom'],
                        ffvl_station['latitude'],
                        ffvl_station['longitude'],
                        Status.GREEN,
                        altitude=ffvl_station['altitude'],
                        url=ffvl_station['url'])
                    stations[station['_id']] = station

                except ProviderException as e:
                    self.log.warning(f"Error while processing station '{ffvl_id}': {e}")
                except Exception as e:
                    self.log.exception(f"Error while processing station '{ffvl_id}': {e}")

        except ProviderException as e:
            self.log.warning(f'Error while processing stations: {e}')
        except Exception as e:
            self.log.exception(f'Error while processing stations: {e}')

        try:
            @retry(wait=wait_random_exponential(multiplier=2, min=2), stop=stop_after_delay(60),
                   after=after_log(self.log, logging.WARNING))
            def request_data():
                # data.ffvl.fr randomly returns an empty file instead the json doc
                result = requests.get(
                    'http://data.ffvl.fr/json/relevesmeteo.json', timeout=(self.connect_timeout, self.read_timeout))
                return result.json()

            ffvl_measures = request_data()

            ffvl_tz = tz.gettz('Europe/Paris')
            for ffvl_measure in ffvl_measures:
                station_id = None
                try:
                    ffvl_id = ffvl_measure['idbalise']
                    station_id = self.get_station_id(ffvl_id)
                    if station_id not in stations:
                        raise ProviderException(f"Unknown station '{station_id}'")
                    station = stations[station_id]

                    measures_collection = self.measures_collection(station_id)
                    new_measures = []

                    key = arrow.get(ffvl_measure['date'], 'YYYY-MM-DD HH:mm:ss').replace(tzinfo=ffvl_tz).timestamp

                    if not self.has_measure(measures_collection, key):
                        measure = self.create_measure(
                            station,
                            key,
                            ffvl_measure['directVentMoy'],
                            ffvl_measure['vitesseVentMoy'],
                            ffvl_measure['vitesseVentMax'],
                            temperature=ffvl_measure['temperature'],
                            humidity=ffvl_measure['hydrometrie'],
                            pressure=Pressure(qfe=ffvl_measure['pression'], qnh=None, qff=None)
                        )
                        new_measures.append(measure)

                    self.insert_new_measures(measures_collection, station, new_measures)

                except ProviderException as e:
                    self.log.warning(f"Error while processing measures for station '{station_id}': {e}")
                except Exception as e:
                    self.log.exception(f"Error while processing measures for station '{station_id}': {e}")

        except ProviderException as e:
            self.log.warning(f'Error while processing FFVL: {e}')
        except Exception as e:
            self.log.exception(f'Error while processing FFVL: {e}')

        self.log.info('...Done!')
Exemplo n.º 7
0
    def process_data(self):
        try:
            self.log.info('Processing Holfuy data...')
            holfuy_stations = requests.get(
                'https://api.holfuy.com/stations/stations.json',
                timeout=(self.connect_timeout, self.read_timeout)).json()
            holfuy_data = requests.get(
                'https://api.holfuy.com/live/?s=all&m=JSON&tu=C&su=km/h&utc',
                timeout=(self.connect_timeout, self.read_timeout)).json()
            holfuy_measures = {}
            for holfuy_measure in holfuy_data['measurements']:
                holfuy_measures[holfuy_measure['stationId']] = holfuy_measure

            for holfuy_station in holfuy_stations['holfuyStationsList']:
                holfuy_id = None
                station_id = None
                try:
                    holfuy_id = holfuy_station['id']
                    name = holfuy_station['name']
                    location = holfuy_station['location']
                    latitude = location.get('latitude')
                    longitude = location.get('longitude')
                    if (latitude is None
                            or longitude is None) or (latitude == 0
                                                      and longitude == 0):
                        raise ProviderException('No geolocation found')
                    altitude = location.get('altitude')

                    urls = {
                        lang: url.format(id=holfuy_id)
                        for lang, url in self.provider_urls.items()
                    }
                    station = self.save_station(holfuy_id,
                                                name,
                                                name,
                                                latitude,
                                                longitude,
                                                Status.GREEN,
                                                altitude=altitude,
                                                url=urls)
                    station_id = station['_id']

                    measures_collection = self.measures_collection(station_id)
                    new_measures = []

                    if holfuy_id not in holfuy_measures:
                        raise ProviderException(
                            f"Station '{name}' not found in 'api.holfuy.com/live/'"
                        )
                    holfuy_measure = holfuy_measures[holfuy_id]
                    last_measure_date = arrow.get(holfuy_measure['dateTime'])
                    key = last_measure_date.timestamp
                    if not self.has_measure(measures_collection, key):
                        measure = self.create_measure(
                            station,
                            key,
                            holfuy_measure['wind']['direction'],
                            Q_(holfuy_measure['wind']['speed'],
                               ureg.kilometer / ureg.hour),
                            Q_(holfuy_measure['wind']['gust'],
                               ureg.kilometer / ureg.hour),
                            temperature=Q_(holfuy_measure['temperature'],
                                           ureg.degC)
                            if 'temperature' in holfuy_measure else None,
                            pressure=Pressure(
                                qfe=None,
                                qnh=Q_(holfuy_measure['pressure'], ureg.hPa)
                                if 'pressure' in holfuy_measure else None,
                                qff=None))
                        new_measures.append(measure)

                    self.insert_new_measures(measures_collection, station,
                                             new_measures)

                except ProviderException as e:
                    self.log.warning(
                        f"Error while processing station '{station_id or holfuy_id}': {e}"
                    )
                except Exception as e:
                    self.log.exception(
                        f"Error while processing station '{station_id or holfuy_id}': {e}"
                    )

        except Exception as e:
            self.log.exception(f'Error while processing Holfuy: {e}')

        self.log.info('Done !')
Exemplo n.º 8
0
    def process_data(self):
        try:
            self.log.info('Processing Pioupiou data...')
            result = requests.get(
                'http://api.pioupiou.fr/v1/live-with-meta/all',
                timeout=(self.connect_timeout, self.read_timeout))
            station_id = None
            for piou_station in result.json()['data']:
                try:
                    piou_id = piou_station['id']
                    location = piou_station['location']
                    latitude = location.get('latitude')
                    longitude = location.get('longitude')
                    if (latitude is None
                            or longitude is None) or (latitude == 0
                                                      and longitude == 0):
                        continue

                    location_date = None
                    if location['date']:
                        try:
                            location_date = arrow.get(location['date'])
                        except ParserError:
                            pass

                    station = self.save_station(
                        piou_id,
                        None,
                        None,
                        latitude,
                        longitude,
                        self.get_status(station_id,
                                        piou_station['status']['state'],
                                        location_date, location['success']),
                        url=urllib.parse.urljoin(self.provider_url,
                                                 str(piou_id)),
                        default_name=piou_station.get('meta',
                                                      {}).get('name', None))
                    station_id = station['_id']

                    measures_collection = self.measures_collection(station_id)
                    new_measures = []

                    piou_measure = piou_station['measurements']
                    last_measure_date = arrow.get(piou_measure['date'])
                    key = last_measure_date.timestamp
                    if not self.has_measure(measures_collection, key):
                        measure = self.create_measure(
                            station,
                            key,
                            piou_measure['wind_heading'],
                            piou_measure['wind_speed_avg'],
                            piou_measure['wind_speed_max'],
                            pressure=Pressure(qfe=piou_measure['pressure'],
                                              qnh=None,
                                              qff=None))
                        new_measures.append(measure)

                    self.insert_new_measures(measures_collection, station,
                                             new_measures)

                except ProviderException as e:
                    self.log.warn(
                        f"Error while processing station '{station_id}': {e}")
                except Exception as e:
                    self.log.exception(
                        f"Error while processing station '{station_id}': {e}")

        except Exception as e:
            self.log.exception(f'Error while processing Pioupiou: {e}')

        self.log.info('Done !')
Exemplo n.º 9
0
    def save_measures(self, jdc_id, blocs, stations_metadata):
        try:
            jdc_station = list(
                filter(lambda d: str(d['id']) == jdc_id, stations_metadata))[0]
            station = self.save_station(jdc_id,
                                        jdc_station['short_name'],
                                        jdc_station['name'],
                                        jdc_station['latitude'],
                                        jdc_station['longitude'],
                                        self.get_status(jdc_station['status']),
                                        altitude=jdc_station['altitude'],
                                        url=urllib.parse.urljoin(
                                            self.provider_url,
                                            '/station/' + jdc_id))
            station_id = station['_id']

            try:
                jdc_measures = blocs[0]['mesures']
            except Exception:
                self.log.warning('Unable to find a bloc with measures')
                jdc_measures = []

            self.log.info(
                f"Station '{jdc_id}' ({station['name']}) found {len(jdc_measures)} measures"
            )

            measures_collection = self.measures_collection(station_id)
            for jdc_measure in jdc_measures:
                key = jdc_measure['datetime']
                if not self.has_measure(measures_collection, key):
                    try:
                        new_measure = self.create_measure(
                            station,
                            key,
                            self.find_value(jdc_measure, 'Direction du vent'),
                            self.find_value(jdc_measure, 'Vent moyen'),
                            self.find_value(jdc_measure, 'Vent max'),
                            temperature=self.find_value(
                                jdc_measure, "Température de l'air"),
                            humidity=self.find_value(jdc_measure, 'Humidité'),
                            pressure=Pressure(qfe=self.find_value(
                                jdc_measure, 'Pression atmosphérique'),
                                              qnh=None,
                                              qff=None),
                            rain=self.find_value(jdc_measure, 'Pluviométrie'))
                        self.insert_new_measures(measures_collection, station,
                                                 [new_measure])
                    except ProviderException as e:
                        self.log.warning(
                            f"Error while processing measure '{key}' for station '{station_id}': {e}"
                        )
                    except Exception as e:
                        self.log.exception(
                            f"Error while processing measure '{key}' for station '{station_id}': {e}"
                        )

        except ProviderException as e:
            self.log.warning(f"Error while processing station '{jdc_id}': {e}")

        except Exception as e:
            self.log.exception(
                f"Error while processing station '{jdc_id}': {e}")
    def process_data(self):
        try:
            self.log.info('Processing MeteoSwiss data...')

            url_pattern = 'https://data.geo.admin.ch/ch.meteoschweiz.messwerte-{parameter}/' \
                          'ch.meteoschweiz.messwerte-{parameter}_en.json'

            main_wind = requests.get(url_pattern.format(parameter='windgeschwindigkeit-kmh-10min'), timeout=(
                self.connect_timeout, self.read_timeout)).json()
            wind_gust = requests.get(url_pattern.format(parameter='wind-boeenspitze-kmh-10min'), timeout=(
                self.connect_timeout, self.read_timeout)).json()
            temperature = requests.get(url_pattern.format(parameter='lufttemperatur-10min'), timeout=(
                self.connect_timeout, self.read_timeout)).json()
            humidity = requests.get(url_pattern.format(parameter='luftfeuchtigkeit-10min'), timeout=(
                self.connect_timeout, self.read_timeout)).json()
            pressure_qfe = requests.get(url_pattern.format(parameter='luftdruck-qfe-10min'), timeout=(
                self.connect_timeout, self.read_timeout)).json()
            pressure_qnh = requests.get(url_pattern.format(parameter='luftdruck-qnh-10min'), timeout=(
                self.connect_timeout, self.read_timeout)).json()
            pressure_qff = requests.get(url_pattern.format(parameter='luftdruck-qnh-10min'), timeout=(
                self.connect_timeout, self.read_timeout)).json()
            rain = requests.get(url_pattern.format(parameter='niederschlag-10min'), timeout=(
                self.connect_timeout, self.read_timeout)).json()

            if main_wind['creation_time'] != wind_gust['creation_time'] != temperature['creation_time'] != \
                    humidity['creation_time'] != pressure_qfe['creation_time'] != pressure_qnh['creation_time'] != \
                    pressure_qff['creation_time'] != rain['creation_time']:
                self.log.error('Creation time of parameters files are not the same')

            main_wind_data = main_wind['features']
            wind_gust_data = self.to_dict(wind_gust['features'])
            temperature_data = self.to_dict(temperature['features'])
            humidity_data = self.to_dict(humidity['features'])
            pressure_qfe_data = self.to_dict(pressure_qfe['features'])
            pressure_qnh_data = self.to_dict(pressure_qnh['features'])
            pressure_qff_data = self.to_dict(pressure_qff['features'])
            rain_data = self.to_dict(rain['features'])

            station_id = None
            for meteoswiss_station in main_wind_data:
                try:
                    meteoswiss_id = meteoswiss_station['id']
                    location = meteoswiss_station['geometry']['coordinates']
                    urls = {lang: url.format(param='messwerte-windgeschwindigkeit-kmh-10min', id=meteoswiss_id) for
                            lang, url in self.provider_urls.items()}

                    station = self.save_station(
                        meteoswiss_id,
                        meteoswiss_station['properties']['station_name'],
                        meteoswiss_station['properties']['station_name'],
                        ch_to_wgs_lat(location[0], location[1]),
                        ch_to_wgs_lon(location[0], location[1]),
                        Status.GREEN,
                        altitude=meteoswiss_station['properties']['altitude'],
                        tz='Europe/Zurich',
                        url=urls)
                    station_id = station['_id']

                    timestamp = meteoswiss_station['properties'].get('reference_ts', None)
                    if not timestamp:
                        self.log.warning(f"'{station_id}' has no timestamp field")
                        continue
                    key = arrow.get(meteoswiss_station['properties']['reference_ts'], 'YY-MM-DDTHH:mm:ZZ').timestamp

                    measures_collection = self.measures_collection(station_id)
                    new_measures = []

                    if meteoswiss_id in temperature_data:
                        temperature = self.get_value(temperature_data[meteoswiss_id]['properties'], unit=ureg.degC)
                    else:
                        temperature = None

                    if meteoswiss_id in humidity_data:
                        humidity = humidity_data[meteoswiss_id]['properties']['value']
                    else:
                        humidity = None

                    if meteoswiss_id in pressure_qfe_data:
                        pressure = Pressure(
                            qfe=self.get_value(pressure_qfe_data[meteoswiss_id]['properties']),
                            qnh=self.get_value(pressure_qnh_data[meteoswiss_id]['properties']),
                            qff=self.get_value(pressure_qff_data[meteoswiss_id]['properties']))
                    else:
                        pressure = None

                    if meteoswiss_id in rain_data:
                        # 1mm = 1 liter/m^2
                        rain = self.get_value(rain_data[meteoswiss_id]['properties'],
                                              unit=ureg.liter / (ureg.meter ** 2))
                    else:
                        rain = None

                    if not self.has_measure(measures_collection, key):
                        measure = self.create_measure(
                            station,
                            key,
                            meteoswiss_station['properties']['wind_direction'],
                            self.get_value(meteoswiss_station['properties']),
                            self.get_value(wind_gust_data[meteoswiss_id]['properties']),
                            temperature=temperature,
                            humidity=humidity,
                            pressure=pressure,
                            rain=rain
                        )
                        new_measures.append(measure)

                    self.insert_new_measures(measures_collection, station, new_measures)

                except ProviderException as e:
                    self.log.warning(f"Error while processing station '{station_id}': {e}")
                except Exception as e:
                    self.log.exception(f"Error while processing station '{station_id}': {e}")

        except Exception as e:
            self.log.exception(f'Error while processing MeteoSwiss: {e}')

        self.log.info('...Done!')