A digital picture frame with weather forecast

Reuse and Recycle

© Lead Image © Christos Georghiou, 123RF.com

© Lead Image © Christos Georghiou, 123RF.com

Article from Issue 233/2020
Author(s):

A digital picture frame displays photographs and a current weather forecast with just a few hundred lines of Bash and a Raspberry Pi.

Not all that long ago I was thinking it would be pretty neat to buy the small-form-factor SheevaPlug computer  [1]. However, it was pretty pricey for a computer for which I had no specific use, so I never bought it. All of that went out the window when the pretty powerful and super affordable Raspberry Pi came out in 2012. Although I didn't have any immediate project in mind, I lined up with everyone else to purchase one.

Once I received my Raspberry Pi, I set out to create projects (e.g., a proxy server, LED cube [2], and networked music device [3]) just to get started. I also experimented with the I2C and SPI protocols and played with devices previously in the domain of the Arduino.

Before I knew it, I had a small collection of these neat little devices. Over time, however, they fell out of use. These classic Raspberry Pis still work, but they aren't as fast and as capable as the most recent Raspberry Pi. While visiting my parents last summer, I saw their old unused TFT monitor in the corner, and it occurred to me how it could be reused. A 15-inch monitor is nothing special when connected to a PC, but it is pretty fabulous when turned into an electronic picture frame.

Most electronic picture frames, usually 8 to 10 inches measured diagonally, simply cycle through photos either in internal memory or on an SD card. The task is well within the capabilities of the Raspberry Pi, but I had another twist that would make this a premium solution. I don't visit my folks as often as I would like, but I would like pictures of their grandchildren always displayed prominently.

What I envisioned was as picture frame connected to common data storage that could be maintained remotely and to which photos could be downloaded automatically. Yet considering the non-technical nature of my parents, the picture frame would need to be self-maintaining.

To justify the counter space for a 15-inch monitor, I would really need to convince my folks of the extra utility this solution would bring. My mom keeps a pretty close eye on the weather forecasts, so I thought the picture frame could also retrieve current weather information.

The picture frame functionality can be summarized in a few words, but implementing the solution would require a fair number of "moving parts":

  • LCD monitor
  • Raspberry Pi
  • SD card
  • USB stick
  • HDMI-to-VGA adapter cable
  • WiFi dongle/Ethernet cable
  • Weather data
  • Shared Internet data source

The hardware in my case was an old Raspberry Pi B with a WiFi dongle. The setup of the operating system was just a matter of imaging an SD card [4] with an image from the Raspberry Pi site. For this project, it was important that the Raspberry Pi boot automatically and log in to the desktop to display pictures. Although not a requirement, SSH is useful during development and perhaps later for support.

Helper Tools

All functionality would be controlled from a few Bash scripts, with a few utilities to perform some of the tasks:

apt-get install curl jq feh

curl retrieves data with URLs. More specifically, it will be used to retrieve weather data. Information found on the Internet comes in a number of formats, but one of the easiest data formats to use for most web pages is JSON, because it is not so wordy as XML. Even so, it is a bit unwieldy when used from the command line without some additional help, which comes in the form of the command-line utility jq, a lightweight JSON processor. This utility allows individual values to be selected out of a JSON structure without a lot of complicated syntax:

data.json
{
  "temp": 14.15,
  "pressure": 1009,
  "humidity": 87,
  "temp_min": 12.22,
  "temp_max": 15.56
}

Like other command-line tools, the jq command can process either a file or an input stream:

cat data.json | jq -r .pressure
>1009

A graphics program, preferably one that can be run from the command line, will display the photos. The feh program does all of this, and the -F option ensures the menu and taskbar are hidden. The feh image viewer can display a complete slideshow, or it can display a single image. The single-image display makes it the perfect tool and gives complete yet granular control over which images are displayed and for how long:

feh -F -x <picture fn>

The Raspberry Pi can have a large SD card or even an additional USB pen drive for picture storage, but a mutually accessible attached drive requires the Internet. A number of cloud solutions could make external storage available, but I wanted a solution that also had a friendly web interface.

Data Storage

Dropbox, one of the original data drives on the Internet, provides free disk space (2GB) and a web interface for access. Although 2GB is not a lot of space for many tasks, it should be plenty for holding a few photographs. (See also the "Google Drive" box.)

Google Drive

My initial Internet data drive was not Dropbox, but Google Drive. Google has a much larger storage space of 15GB associated with each existing email account and has the community-supported gdrive client on GitHub [5] that performs much like the Dropbox command-line tool. One slight difference between the two clients is that the Google Drive client operates on file IDs, not file names.

When I started this project, I used the gdrive client, but while re-verifying all of the steps, I discovered that the client no longer worked for new email addresses. It turns out the original developer embedded their application ID into the client and either the ID was revoked, or it hit some magical limit at Google and was disabled.

If you prefer to use Google Drive, the source code does exist. It is simply a matter of registering with Google and recompiling the client. If you are comfortable with the Go programming language or would like to learn a bit about it, this might be an interesting project.

The dbxcli command-line tool [6] lets you access Dropbox as a drive. This client is available for a few platforms other than Linux, such as macOS and BSD. Yet before you can use this client, you must connect it to the Dropbox account with your credentials. The first time you run the client you are prompted for verification (Figure 1).

Figure 1: First time running the dbxcli client.

Entering the URL into your browser in response brings up the login dialog. When you enter your credentials, you will be asked if it is acceptable for this tool to have access to your Dropbox account (Figure 2). Pressing the Allow button brings up your verification code in a new dialog. Simply copy and paste the displayed code into your terminal session to finish setting up the dbxcli client.

Figure 2: Enabling Dropbox access.

Although it isn't important to know how this client works, it creates a .config/dbxcli folder in your home directory that contains an access code to be used as necessary by the dbxcli client. Once the code has been given, the client is set up, allowing control of Dropbox files from the command line. Client operations are somewhat limited but provide more than enough functionality to access Dropbox as an Internet-connected disk. The only operations needed for the picture frame are directory listings (ls), uploading files (put), downloading files (get), and deleting files (rm).

Weather Data

The weather functionality doesn't have very complex requirements: I simply want to get the current temperature and display a brief forecast. Initially I thought about opening up a web page and trying to capture the information there; however, that seemed a bit underhanded as well as difficult. I did find a number of sites that provide free weather information, but OpenWeather [7] was the easiest site to use.

OpenWeather provides different levels of service for retrieving data. Depending on the level of service you select, the data can be as old as a few hours or as recent as 10 minutes. It is possible to get weather forecasts, weather maps, the UV index, weather alerts, or just the current weather. The pricing model depends on the amount of weather or type of historical information needed.

The picture frame will only need at most a few calls per hour, which is considerably less than the 60 calls per second you can make with the free account. OpenWeather is affordable but it also makes its data available over REST API calls, thus eliminating the need to download libraries and compile programs to retrieve data. The one catch is that you have to sign up to use their service.

Once you sign up [8], you receive a key (Figure 3); with this token you are able to download your weather data by the API. You can even create additional keys for specific purposes.

Figure 3: The OpenWeather key maintenance screen.

OpenWeather has quite a number of REST calls, each of which fetch different types of weather data. Each API accepts a number of parameters, which makes it easy to customize the results. What is really nice is the consistency of parameters between different REST calls, making it easier to understand when you are looking at new REST calls.

When signing up, you receive an API key, or APPID (Figure 3), which is required for OpenWeather to associate your requests with a valid user for the premium function calls. However, if you do not provide your APPID parameter, you cannot even call their free services.

OpenWeather provides quite a number of ways to define for which city or location you want to retrieve weather. The most unambiguous method would be to find your desired city in the list of cities. You can get a list of all weather stations and their unique IDs, as well as their locations as longitude, latitude, city name, and country [9]. The API allows you to pass in the city name and country, although this doesn't work quite as well for the United States.

The problem I had with their list was trying to distinguish between which entry was Minneapolis, Minnesota, and which was Minneapolis, Kansas. OpenWeather does not appear to make any distinction between the US states, so passing in a popular city name might not return the city data you are expecting. To resolve this problem, I had to use a reverse lookup site on the Internet [10].

To select the current temperature or retrieve a weather forecast, you would use:

http://api.openweathermap.org/data/2.5/weather
http://api.openweathermap.org/data/2.5/forecast

The parameters in Table 1 can be used with your requests, as well. If you want to keep your network requests to a minimum, you can use the group call. Simply pass in a comma-separated list of city IDs to receive a JSON structure for each:

http://api.openweathermap.org/data/2.5/group?id=2925533,5037649

Table 1

REST API Parameters

Parameter

Description

appid

The value associated with your OpenWeather user account.

q

The city name, which should include the country for clarity (i.e., London, UK) but is not mandatory.

id

The weather site.

units

The default is Kelvin, which isn't so friendly for normal people; however, you can change the units to metric or imperial (i.e., units=metric).

mode

The data returned is in JSON format by default. If you would prefer either XML or HTML, you can select that format with the mode parameter.

lang

Most data returned by OpenWeather does not need internationalization; however, a small description field gives a hint about the weather, such as light rain or sunny. By assigning the lang parameter, you can see these weather hints in the language of your choice.

Although not a comprehensive look at all the calls you can use to retrieve data from this service, it does show all of the important methods I used to generate my weather forecast.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus

Direct Download

Read full article as PDF:

Price $2.95

News