2

I want to set points on a map layer with autofilled data in some fields in the attribute table, which already works fine with date/time and username/observer.

Is there also a way to capture real time weather data every time a point is set on the layer? (E.g. temperature, humidity and sight)

I have access to an API Key of OpenWeatherMap.

3
  • 7
    Do you have a data source?
    – Erik
    Apr 6, 2021 at 13:24
  • 5
    Are you capturing your own data or using a weather api?
    – Mapperz
    Apr 6, 2021 at 13:38
  • 1
    Yes I have a data source / api key (OpenWeatherMap).
    – Zess
    Apr 6, 2021 at 15:13

1 Answer 1

6

You could use a custom function such as:

from qgis.core import *
from qgis.gui import *
import urllib.request
import urllib
import json

@qgsfunction(args='auto', group='Custom')
def jsonfromurl(url, feature, parent):
    header = {"accept":"application/json"}
    request = urllib.request.Request(url)
    response = urllib.request.urlopen(request)
    response_data = response.read()
    encoding = response.info().get_content_charset('utf-8')
    data = json.loads(response_data.decode(encoding))
    #txt = json.dumps(data) #uncomment this line to receive data as string. also change next line to: return txt
    return data

This function will get a JSON-Response from a given URL.

Open the expression dialog, for example via field calculator, and go to the "Function Editor"-Tab:

enter image description here

Save and load the custom function. Then go back to the regular "Expression"-Tab. Here you can use the new function. Dont forget to insert your personal API-Key.

Here some usage examples:

Get the "main"-content for your current location:

map_get(
jsonfromurl('http://api.openweathermap.org/data/2.5/weather?lat=' ||$y || '&lon=' || $x || '&appid=' || 'yourapikeyhere'),
'main')

enter image description here

Get the temperature for lat=35 and lon=139:

map_get(
map_get(
jsonfromurl('http://api.openweathermap.org/data/2.5/weather?lat=35&lon=139&appid=' || 'yourapikeyhere'),
'main'),
'temp')

enter image description here

Get the wind speed of the current location:

map_get(
map_get(
jsonfromurl('http://api.openweathermap.org/data/2.5/weather?lat=' ||$y || '&lon=' || $x || '&appid=' || 'yourapikeyhere'),
'wind'),
'speed')

enter image description here

If you want to get the current location, make sure your layer is in EPSG:4326 (or use transform(), e.g. map_get(map_get(jsonfromurl('http://api.openweathermap.org/data/2.5/weather?lat=' ||y(transform($geometry,layer_property(@layer,'crs'),'EPSG:4326')) || '&lon=' || x(transform($geometry,layer_property(@layer,'crs'),'EPSG:4326')) || '&appid=' || 'yourapikeyhere'),'wind'),'speed')).

If you need metric units from the response, just add units=metric to the url. For example:

map_get( map_get( jsonfromurl('http://api.openweathermap.org/data/2.5/weather?units=metric&lat=' ||$y || '&lon=' || $x || '&appid=' || 'yourapikeyhere'), 'main'), 'temp')

As you can see, you need to change map_get() and/or the URL depending on what you want to receive. Check out openweathermap API docs for details: https://openweathermap.org/current#geo or look at their example response, e.g.:

{"coord":{"lon":139,"lat":35},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04n"}],"base":"stations","main":{"temp":282.1,"feels_like":281.16,"temp_min":279.82,"temp_max":284.82,"pressure":1013,"humidity":76},"visibility":10000,"wind":{"speed":1.95,"deg":63,"gust":2.92},"clouds":{"all":59},"dt":1617734050,"sys":{"type":3,"id":2019346,"country":"JP","sunrise":1617740571,"sunset":1617786549},"timezone":32400,"id":1851632,"name":"Shuzenji","cod":200}

If you enter this expression as default value in attributes form, it will be the standard-value for your field:

enter image description here

Example result:

enter image description here

8
  • Thanks, this helps a lot! With some fixed lat&long it works. But if I type in the string for my current location, it shows me: Eval Error: HTTP Error 400: Bad Request (?)
    – Zess
    Apr 7, 2021 at 8:20
  • WGS84 / Pseudo-Mercator
    – Zess
    Apr 7, 2021 at 12:00
  • 1
    @Zess Make sure your layer is in WGS 84 (EPSG:4326). OpenWeatherMap only works with lat lon as far as I know. Alternatively you can use transform(). See my edit.
    – MrXsquared
    Apr 7, 2021 at 12:41
  • Ok. I noticed it works on any other layer in WGS84, just not on that specific one... I guess i just will build it new from scratch. Anyway, awesome it works! Last thing to do would be to convert the units into the metric system (units=metric?). I tried but failed.
    – Zess
    Apr 7, 2021 at 13:30
  • 1
    Just add units=metric to the url. For example: map_get( map_get( jsonfromurl('http://api.openweathermap.org/data/2.5/weather?units=metric&lat=' ||$y || '&lon=' || $x || '&appid=' || 'yourapikeyhere'), 'main'), 'temp'). You can read this and more details up at openweathermap.org/current
    – MrXsquared
    Apr 7, 2021 at 16:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.