Uploading to the Weather Underground API

Since all data processing for Meteodrenthe is custom made, this includes sending updates to Weather Underground (WU). I realize that the name of WU has been tarnished in recent years. Nevertheless, it is still one of the most popular websites for PWS owners. Meteodrenthe uploads data there as well. This PWS page is updated once a minute through an automatic process running on the Meteodrenthe server. To achieve this, the WU API is used.

The API documentation is not the easiest to find. This page explains it in some detail. How are updates sent? Below, I assume you know how to execute an HTTP request from whatever piece of code you may have running that processes your data.

WU requires a GET request to the following URL:

https://rtupdate.wunderground.com/weatherstation/updateweatherstation.php

There are a few required GET parameters to get any request to their API to work.

First, you need to identify the device the update is intended for. In your WU account, you have the option to add devices, which receive an ID and a KEY upon creation.

These two values must be passed along with the request as parameters ID and PASSWORD.

There are two other required parameters, action and dateutc. When sending an update, the action type for your request must be set to ‘updateraw’. The date parameters should be a date in format’ dd-MM-YYYY HH:mm:ss’.  Note that the timezone should be UTC, and not the timezone local to the weather station. Alternatively, the API allows the string ‘now’ when you do not want to supply a specific timestamp for the measurement.

So, any successful request must include these GET parameters:

ID=<DEVICE_ID>,PASSWORD=<DEVICE_KEY>,action=updateraw,dateutc=now

Obviously, DEVICE_ID and DEVICE_KEY should be replaced with the values specific to your case. The value for dateutc may also be a date.

Then there are numerous additional parameters representing measurements. I only use a few, but this is the entire list:

winddir - [0-360 instantaneous wind direction]
windspeedmph - [mph instantaneous wind speed]
windgustmph - [mph current wind gust, using software specific time period]
windgustdir - [0-360 using software specific time period]
windspdmph_avg2m  - [mph 2 minute average wind speed mph]
winddir_avg2m - [0-360 2 minute average wind direction]
windgustmph_10m - [mph past 10 minutes wind gust mph ]
windgustdir_10m - [0-360 past 10 minutes wind gust direction]
humidity - [% outdoor humidity 0-100%]
dewptf- [F outdoor dewpoint F]
tempf - [F outdoor temperature] 
 * for extra outdoor sensors use temp2f, temp3f, and so on
rainin - [rain inches over the past hour)] -- the accumulated rainfall in the past 60 min
dailyrainin - [rain inches so far today in local time]
baromin - [barometric pressure inches]
weather - [text] -- metar style (+RA)
clouds - [text] -- SKC, FEW, SCT, BKN, OVC
soiltempf - [F soil temperature]
 * for sensors 2,3,4 use soiltemp2f, soiltemp3f, and soiltemp4f
soilmoisture - [%]
* for sensors 2,3,4 use soilmoisture2, soilmoisture3, and soilmoisture4
leafwetness - [%]
+ for sensor 2 use leafwetness2
solarradiation - [W/m^2]
UV - [index]
visibility - [nm visibility]
indoortempf - [F indoor temperature F]
indoorhumidity - [% indoor humidity 0-100]

For completeness, let me share the Java method I use that actually executes the HTTP request.

    public void uploadToWeatherUnderground(WundergroundData wud) {
        log.info("Uploading current weather to Weather Underground");
        String uri = "https://rtupdate.wunderground.com";
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(uri);
        builder.path("/weatherstation/updateweatherstation.php");
        builder.queryParam("ID", "<DEVICE_ID>");
        builder.queryParam("PASSWORD", "<DEVICE_KEY>");
        builder.queryParam("action", "updateraw");
        builder.queryParam("dateutc", "now");
        builder.queryParam("tempf", wud.getTemperatureF());
        builder.queryParam("dewptf", wud.getDewpointF());
        builder.queryParam("humidity", wud.getHumidity());
        builder.queryParam("windgustmph", wud.getWindGustMph());
        builder.queryParam("winddir", wud.getWindDir());
        builder.queryParam("windspeedmph", wud.getWindSpeedMph());
        builder.queryParam("baromin", wud.getPressureInches());
        builder.queryParam("rainin", wud.getRainInchesHour());
        builder.queryParam("dailyrainin", wud.getRainInchesToday());
        builder.queryParam("solarRadiation", wud.getSolarradiation());

        URI targetURI = builder.build().encode().toUri();
        try {
            String response = restTemplate.getForObject(targetURI, String.class);
            log.info("Response received: {}", response);
        } catch (RestClientException e) {
            log.warn("Caught exception uploading to WU", e);
        }
    }

The parameter the method receives is a data object containing the relevant measurements. Note that most of the units are American standards. So temperature is sent in Fahrenheit, wind speed in miles per hour and pressure in inches of mercury. For these and other values, conversion methods are used.

For those also coding in Java: the UriComponentsBuilder class as well as the RestTemplate used, are available through the Spring Boot Framework. Documentation on their usage is readily available.

Leave a Reply

Your email address will not be published.