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.
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
- KCSV: The reporting airport's ICAO identifier. This one is for Crossville/Whitson Field in Tennessee. Every airport in the world that reports METARs has a four-letter identifying code (no numbers) where the first letter indicates the airport's region. Some examples: K - US mainland ; P - Alaska/Hawaii ; C - Canada ; M - Mexico/Caribbean ; E - Northern Europe ; L - Southern Europe.
- 282041Z: The time the report was issued. The time is reported in Zulu time (aka military time) which is functionally identical to UTC. The numbers are broken in groups of two to give day-hour-minute. This one gives 28-20-41, which means it was issued (Dec) 28th at 20:41Z or 3:41 PM local time.
- AUTO: The report was automatically generated. Report was not human-generated or checked. Most common at smaller airports and airports without a tower.
- 34006KT: The wind direction and speed. The numbers are read direction-speed; here that is 340-06. The direction is measured in true-north degrees which the wind is blowing from, and the speed is measured in knots. The speed may sometimes be followed by G##, which means that the wind is gusting up to some higher speed.
- 1 1/2SM: The visibility in statute miles. The usual format looks like 6SM for six miles. Here it includes a fraction, so the visibility is 1.5 miles. This value will never be higher than 10SM, which we usually read as unlimited visibility.
- BR: The WX section. This section contains any significant weather events at or near the airport and is located between the visibility and cloud layers. It is not included if there are no weather events to report. The only event in this report is BR, which is code for Mist. Codes can be combined like +TSRA, which stands for heavy thunderstorms rain, or VCFC, which stands for vicinity funnel cloud. Click here for a full list of WX codes.
- OVC002: The cloud layer section. This section contains all cloud layers directly above an airport. Each entry has a layer description and height in hundreds of feet AGL (above ground level). Here we have one layer which is overcast and 200 feet AGL. Click here for a full list of cloud layer codes.
- 08/07: The surface temperature and dew point. All temperatures in aviation are in Celsius. The code is divided temp/dew. Here we have a temperature of 8°C and a dew point of 7°C. If either is in the negatives, there will be an 'M' before the number. The closer these two numbers are to each other, the lower the base cloud layer will be, and there will be a high chance of fog, mist, and low visibility. We can see each of these represented elsewhere in the report.
- A3006: The altimeter setting. This is the barometric pressure in inches of Mercury, the US standard, with the decimal point omitted. This is very important for pilots because air density affects every aspect of an aircraft's performance and is used to determine an aircraft altitude. Standard pressure (1 atm) is 29.92 inHg which is equivalent to the pressure at sea level at 15°C. Here we have an altimeter setting of 30.06 inHG, so the air is more dense than standard.
- RMK ...: The remarks section. This is always the last section of a METAR if it is included and contains any extra information about the reporting station or detailed info on the weather reported. The first remark here is A02, which tells us the station is automated and has a sensor which can differentiate between rain and snow (stations without this sensor appear as A01). The second remark, T00830067 , gives of a more detailed temp/dew reading. Here the detailed temperature is 8.3°C and dew point is 6.7°C. Other items you might find in this section include times a WX event began, the amount of rain that has fallen, and if the station requires maintenance.
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 https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code in the terminal in your home directory and then copy mplate.py and mlogic.py 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 mlogic.py . 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 aviationweather.gov 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 mplate.py 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 atBoot.sh 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:
- VFR : Visual Flight Rules - Visibility > 5SM and Ceiling > 3000ft
- MVFR : Marginal VFR - 5SM > Visibility > 3SM and 3000ft > Ceiling > 1000ft
- IFR : Instrument Flight Rules - 3SM > Visibility > 1SM and 1000ft > Ceiling > 500ft
- LIFR : Low IFR - Visibility < 1SM and Ceiling < 500ft
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.
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 mlogic.py 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.