Wednesday, 26 November 2014

Getting & using data from OpenWeatherMap

It is easy to get local or international weather data (such as current temperature, humidity, wind speed & so on) using the OpenWeatherMap API.

 

This could be very useful to me as part of my bird box project for 2015.


But my immediate concern involves our central heating system, and how to determine the local weather conditions.

At the moment I can't measure the outside temperature using my RaspberryPi server. The unit is just too far from an outside wall, making the cabling route difficult.


OpenWeatherMap and the API


OpenWeatherMap is one of several weather sites offering free access to data via an API (application programming interface). I'm a bit confused because the website mentions an apiKey which is allegedly required, although I don't seem to have had any problems without it (accessing just the basic data).

Edit Nov 2015: as of October 2015 you now need an apiKey


The site is owned by Extreme Electronics Ltd and they provide a number of chargeable support contracts from Developer to Enterprise, in addition to the free API.

All I'm really interested in at the moment is a rough idea of the outside temperature. So just using this web string:-

"http://api.openweathermap.org/data/2.5/weather?q=Horsham,uk&units=metric"

...I can grab metric data for the Horsham area in json format.

By manually 'cleaning up' the incoming string in a text editor (i.e. adding indents and line feeds) we can get a better view of the json data:-

{
    "coord":{
            "lon":-0.33,
            "lat":51.06},
    "sys"{
            "type":1,
            "id":5089,
            "message":0.0804,
            "country":"GB",
            "sunrise":1416814383,
            "sunset":1416844991},
    "weather":[{
            "id":800,
            "main":"Clear",
            "description":"Sky is Clear",
            "icon":"01d"}],
    "base":"cmc stations",
    "main":{
            "temp":7.41,
            "pressure":1027,
            "humidity":81,
            "temp_min":6,
            "temp_max":9.1},
    "wind":{
            "speed":2.1,
            "deg":10,
            "var_beg":320,
            "var_end":40},
    "clouds":{"all":0},
    "dt":1416838358,
    "id":2646557,
    "name":"Horsham",
    "cod":200
}


This makes it easier to understand the data structure, and we can now see there are simple string pairs like "name" : "Horsham" and more complex objects such as "main".

A PHP example


Using PHP on my web server, this crude bit of code is all that is required to display basic data:-

<?php
$jsonurl = "http://api.openweathermap.org/data/2.5/weather?q=Horsham,uk&units=metric";
$json = file_get_contents($jsonurl);
$weather = json_decode($json);
$station = $weather->name;
$humidity = $weather->main->humidity;
$tempC = $weather->main->temp;
$min_tempC = $weather->main->temp_min;
$max_tempC = $weather->main->temp_max;
echo "Weather in ".$station."<br>";
echo "<br>";
echo "Humidity: ".$humidity."%";
echo "<br>";
echo "current temperature: ".$tempC."'C";
echo "<br>";
echo "minimum temperature: ".$min_tempC."'C";
echo "<br>";
echo "maximum temperature: ".$max_tempC."'C";
?>


...and selecting this file with Firefox, the browser window looks like this:-


For my central heating project, I already generate a temperature graph using PHP...

PHP generated graph, notes added manually

...but the existing data (from 3 temperature sensors) is created and put into a file by my Gambas program.

When selected by a remote web browser, the PHP page reads the file and plots the data for the last 5 days.

A Gambas example


I created a Gambas test program by placing 6 visible controls on a form, plus an HTTPClient control to simplify communications.

Gambas Form in design view


I also added the Gambas gb.Web component so I could use the JSON.Decode() method.

The only code in this project is contained within the button click event.



Public Sub Button1_Click()

  Dim hClient As HttpClient
  Dim strWeather As String
  Dim colWeather As Collection
  Dim colWeatherMain As Collection
  Dim colWeatherWind As Collection

  hClient = New HttpClient As "hClient"
  hClient.URL = "http://api.openweathermap.org/data/2.5/weather?q=Horsham,uk&units=metric"
  hClient.Async = False
  hClient.Timeout = 10
  hClient.Get
 
  strWeather = hClient.ReadLine()
  TextArea1.Text = strWeather
  colWeather = JSON.Decode(strWeather)
  TextBox1.Text = "Station: " & colWeather["name"]
  colWeatherMain = colWeather["main"]
  TextBox2.Text = "Temp: " & colWeatherMain["temp"] & "'C"
  TextBox3.Text = "Humidity: " & colWeatherMain["humidity"] & "%"
  colWeatherWind = colWeather["wind"]
  TextBox4.Text = "wind speed: " & colWeatherWind["speed"] & "kph"
Catch
  Me.Text = Error.Text
End



The incoming (json) string can be loaded to a collection (colWeather). String pairs can be decoded at this level, but for objects within this collection we need to create additional collections (colWeatherMain, colWeatherWind).

When this Gambas program is run, the data looks like this:-


My applications


For PiStat I only need the current outside temperature at the moment. This will be plotted along with my house temperatures in an attempt to control the heating more effectively than the current programmable thermostat. But its also possible that predicted temperatures (e.g. 24 hours ahead) may also play a role as this system evolves.

As for my bird box projects, although I have previously recorded temperature and visits/feeding activity, I think any influence due to weather is likely to be wider than just temperature. So having the ability to record data like humidity, rainfall and cloud cover may prove more revealing.

No comments:

Post a Comment