I received a request to demonstrate how to consume JSON web services from a Raspberry Pi. This tutorial demonstrates how to connect to an Internet weather API in python and display city temperatures and conditions from around the world on a 16×2 LCD display. A DHT22 sensor is also connected to display local temperature and humidity.
On a small breadboard I have a 16×2 LCD display, a DHT22 temperature/humidity sensor and dual potentiometers to control contrast and brightness.
Here’s a simplified schematic. The LCD display requires 6 GPIO pins on the Pi. You can pick any pins you like. I’m using GPIO 26 for RS, 19 for enable and 13, 6, 5 and 11 for data 4 through 7 respectively. The LCD Vcc is connected to 5 volts on the Pi. The ground, read/write and backlight cathode are connected to the PI’s ground. The DHT22 sensor runs at 3.3 volts unlike the LCD display which is 5 volts. The data line is connected to GPIO 4. A mandatory 10K ohm pull up resistor is placed between the DHT22 Vcc pin 1 and the data pin 2. Pin 3 is left disconnected. Pin 4 goes to ground.
The LCD contrast pin and the backlight anode pin are connected to wipers on the pots. The other 2 terminals on each pot are connected to a ground and a 5 volt pin. Please check your display datasheet to insure your backlight will tolerate 5 volts. You might have to add a resistor if it requires a lower voltage. Instead of 2 pots, I’m using a single Bourns 7102B on the breadboard which I like because of the small form factor and it also stays securely in place. It’s basically 2 potentiometers in a single dip package.
I’m running the latest release of Raspbian Jesse OS on a Raspberry Pi 2. However, I’ve tested the Adafruit LCD and DHT22 code on earlier Pi’s with Wheezy. I recommend you always start tutorials with a freshly installed OS and perform apt-get update and apt-get upgrade from a terminal to insure the latest packages.
Use pip to install the Adafruit CharLCD library to control the LCD display.
The DHT22 library requires build essentials and python-dev which are installed with apt-get install.
Git clone is used to download the Adafruit Python DHT sensor library. The DHT22 library needs to be installed. CD into the downloaded folder and run sudo python setup.py install. Don’t forget to reboot (it’s required).
After the Pi reboots open a terminal and run idle with gksu to insure you have the necessary super user privileges. (Update: super-user privileges are no longer required for GPIO access with the latest version of Raspbian Jessie.)
To consume JSON web services the python requests library will be used. It is a well-designed library that provides very powerful web capabilities.
The following code for the international weather clock is available for download.
In a python file after the shebang line, requests is imported. Sleep, datetime and sys are also imported.
Import the Adafruit_CharLCD library.
An lcd is instantiated and cleared. The pins selected for the control and data lines are passed as parameters. The display dimensions are also passed. You can use different GPIO pins but you must specify them when you create the lcd. Please note that Adafruit has made breaking changes to the library since the video. The code below has been updated to reflect the changes.
The Adafruit DHT library is imported as dht. The Adafruit installation program took care of adding the DHT library to the path.
A list of tuples of city names and ID’s is declared. The Yahoo Weather API will be used to provide the weather forecast data.
In addition to the list, a string delimited list of just the ID’s will be required for the weather API query. Join is used with list comprehension to extract the codes to a string from the list above.
If you would like to add cities to the list, you can obtain the city ID by going to Yahoo weather and searching for the desired city. In the browser address bar the city ID will be located next to the city name.
A method called getWeatherConditions uses the python Request library to poll the online weather service. First the url of the web service is specified. Two query strings are required. Query strings are basically data appended to the end of a url. They are passed with the web request similarly to how parameters are passed to a function. The first query string is q which stands for query. It is a select statement to query the weather API. In this case, it returns all weather forecasts matching the city ID’s in the city_codes string. The 2nd query string is format which specifies the format of the response to our request. JSON is specified for the format. Headers to disable caching are also included. I’m not sure if they are necessary, but it doesn’t hurt to add just to be sure the data is always current. The requests.get method takes the url, query strings and headers. The method returns a web response which should contain the forecast data in JSON format. The getWeatherCondtion method returns the forecast data. The json method is used to parse the JSON data into a nested dictionary format that works well with python. The method is wrapped with try except to catch and return any errors.
If you prefer Celsius, the query line would be changed as follows:
To work with the returned JSON data in python, it is important to understand nested dictionaries. A python dictionary is as an unordered set of key: value pairs. The keys are unique identifiers that point to a corresponding value. This value can be another dictionary which would be considered nested and it could contain additional nested dictionaries and on and on. For example, the following dict of animals contains keys for birds and mammals which point to nested dictionaries of specific animals including duck and dog which point to the animal sounds quack and woof. Bracket notation is used to reference nested items:
Here is an example of what the returned JSON weather forecast data looks like:
The main while loop will run until interrupted. The above getWeatherConditions method is called. The returned data is checked to make sure it is of type dict and that it does not contain an error message. Any errors are logged and the program pauses for 4 seconds.
If no errors, the total count of returned city data forecasts is retrieved from the JSON data. This should equal the length of the cities list.
The program loops through all the cities. City name is returned from the cities list. Forecast condition text and temperature is returned from the JSON data. Note how the python dict syntax allows us to extract deeply nested JSON data with a single line of code.
Clear is used to clear the LCD display. The lcd.message method is used to display the city name and temperature on the first line.
UPDATE: the Adafruit library changed the name of the write4bits method to write8.
The lcd.write8 method is used to append a degree symbol to the display. LCD display symbols often vary depending on the display and region. Usually the datasheet will contain a character map that has the value of all character symbols. On my display 223 is the decimal value for degree. An ‘F’ for Fahrenheit is appended followed by ‘\n’ for new line which move the cursor to the bottom line of the display. The weather condition text is displayed on the bottom line and the program pauses for a second.
Next, the dht.read_retry method is used to poll the DHT22 sensor connected on GPIO 4 for temperature and humidity. The temperature is returned in Celsius and then converted to Fahrenheit. Omit the conversion line and change the F to a C below if you prefer Celsius.
The display is cleared and the date/time are displayed on the first line. Python’s strftime is used to format the date and time. The directives are not very intuitive but they are well documented on the strftime website. The local temperature and humidity from the DHT22 are displayed on the bottom line. The program pauses for 2 seconds and then the loop continues.
DHT22 Troubleshooting Tips.