This project uses a Raspberry Pi to display METAR weather data. METAR stands for Meteorological Aerodrome Report, and it is the primary resource pilots use to determine an airport's current weather conditions. There are almost 3,500 airports that offer METARs in the US, so it's quite likely there is one near you.


Understanding METARs

A METAR is a single string of text that contains a codified version of the weather conditions at a given airport. They are usually updated once every hour while the airport's air traffic control tower is operational. The exception is when conditions have changed significantly since the last report, eg a significant change in wind speed and/or direction. Below is an example of a real METAR:

KCSV 282041Z AUTO 34006KT 1 1/2SM BR OVC002 08/07 A3006 RMK AO2 T00830067

RasPi Setup

If you haven't read it yet, go here to read my post on setting up a Raspberry Pi for IoT. That will get you most of the way there.

All you need to do to use the LCD Plate is download Adafruit's Raspberry Pi Python Library; just type git clone in the terminal in your home directory and then copy and into Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate/. If you are using the PiTFT display, Adafruit has made an iso (Resistive/Capacitive) with the screen drivers and software ready to run. Note: the link goes to a tutorial for the resistive touchscreen.


The METAR-RasPi project is broken up based on the display hardware and a shared set of functions; this shared set is found in . For anyone wishing to create their own METAR-based project, start with these two functions.

First, getMETAR(station) takes a station identifier string, like 'KJFK', and returns a string containing the station's METAR report. It does this by fetching a webpage from and extracting just the report. If it can't find the report, be it the station doesn't exist, there's no report within the last eight hours, or they changed the webpage layout, the function will return a zero. This can be used in Python with an if statement since non-empty strings are read as True and zeros are read as False.

Second, parseMETAR(txt) takes the report string returned by getMETAR and returns a dictionary of labelled report values with the following keys: Station, Time, Wind-Direction, Wind-Speed, Wind-Gust, Visibility, Altimeter, Temperature, Dewpoint, Cloud-List, Other-List, Remarks. Every key corresponds to a string except for Cloud-List and Other-List which are lists of strings. If the report is incomplete, the keys affected will point to an empty string or an empty list. The parse function only organizes the report; it does not translate it. This means things like a negative temperature will still be expressed as 'M05'.

There are other useful functions which translate WX data, determine the station's flight rules, and determine the ceiling from the Cloud-List.


The first display this program was designed for was the Adafruit RGB Negative 16x2 LCD. It has a 16x2 LCD char display, RGB backlight, and five interface buttons, and it fits snugly on the Raspberry Pi's GPIO pins. Given that the data we want to display is already a formatted line of text, this is the most basic way to do that. However, we can use the buttons and backlight to provide additional functionality.

Creating a display with some static variables, in this case a station ID, is fairly straightforward. However, allowing the user to change the station while the program is running requires a UI. With the plate, this means using those five buttons. They are arranged on the plate like a d-pad and select button, which leads to some obvious input choices like on the station id selection screen. Other choices, not so.

In order to write this program without having to use threading, the program checks for any button input at the end of each line scroll. If the select button is held down then, the station selection screen returns. If the right and left buttons are held at the same time (whether here or on the selection screen), the user is prompted if they want to turn off the Pi or exit the program; the option available is determined by a boolean in the file. If you want to create a closed system, ie run at boot and shutdown, make sure that shutdownOnExit is set to True and that is set to run at boot. If you need help doing this, I have a blog post about what I always do when setting up a new RPi (link soon to come), which includes how to setup an file.

It's one thing to display some data; it's different, and more fun, to make sense of that data. Since we have already parsed the text, we can use the visibility and ceiling to determine the station's current flight rules. We use getFlightRules(vis , cld) to do this. Here, vis is just the value of Visibility. However, cld must be the cloud ceiling. By definition, the ceiling is the lowest Broken (BKN) or Overcast (OVC) layer of clouds. For METARs, we also include Vertical Visibility (VV) in cases where the observer can't see the clouds like in heavy fog. We use the function getCeiling(clouds) where clouds is Cloud-List. Now we run getFlightRules to get one of four possible flight conditions:

The colors shown above are those which are commonly associated with each flight condition. We can use the RGB backlight to change the display color to communicate this without having to add any more text to the display. It also allows anyone to generalize what the weather is like without having to see any of the text.

Note: the plate does not display the remarks section by default. It generally is not as useful as the rest of the report and would add too much extra text to the scrolling line, sometimes tripling its length. If you want to enable this, set the value of includeRemarks to True.

METAR Screen

Many of my projects start out with me saying "Ok, what haven't I really used in a project yet." That led to using the plate above but also my first real attempt at a screen UI. In keeping with the small form factor, the new interface was designed for the Adafruit 320x240 PiTFT display. You can see a demonstration video at the top of the page. Some UI elements carried over from the plate, like the METAR selection screen, while others were infeasible, like the flight rules backlight, which became only that element's text color. That being said, the clear advantages of using the screen over the plate are having more potential inputs and being able to display much more information.

With the plate, the only input options were combinations of those five hardware buttons. With the screen, we can place inputs anywhere we want…or nowhere at all. Two sections of the METAR, WX and Remarks, are always of variable length and may not be included at all. To work with this and save space on the main display, both have been given their own screen which is accessible by a dynamic button just above the settings button. The appearance changes depending on the available data, so it will say "WX", "RMK", "WX/RMK", or not appear at all. Now that this data can take up the entire screen, we can expand it. Since there are a finite number of WX codes, it's easy to translate each combination using translateWX(wx) from the library. For simplicity's sake, we leave the remarks alone.

Rather than just display text, we can create graphics to more effectively communicate the METAR data. The best example of this is the cloud layer height that takes over the right side of the display. It shows a graph of all the cloud layers relative to themselves and the ground with the top of the graph being 8,000ft. If the highest layer is above 8,00ft, that becomes the new top and the rest of the layers scale accordingly. The METAR's text is still the same, but now the user can better visualize what that data means.

There are other value-add things we can do. Because we've already parsed the data, each item can be displayed and labelled by itself. Rather than displaying 36010G14KT, it's trivial to break it out as 360°, 10kts, and 14kt gusts. The temperature and dew point can be used to calculate the humidity.


Aviation Weather Center -