/ python

Tooling Tuesday - NASA API and Python

So I love space, NASA and Python...oh and pretty backgrounds!

So while I was working on my Adafruit PyPortal review, I followed their excellent NASA Image of the day project and thought...

"That would be cool for my desktop wallpaper!"

So with that in my head I started to write some code while I was at Blackpool Makerspace.

So what are we building?

A Python application that will change the desktop wallpaper on our Ubuntu machine to match the latest image from NASA's Astronomy Picture of the Day.

So what is the NASA API?

Screenshot-from-2019-04-30-12-08-04

An API is an Application Programming Interface which means that we have a way to work with data provided by an organisation. The data is typically provided as JSON (JavaScript Object Notation) which for those familiar with Python looks and works a bit like the dictionary data type.

Screenshot-from-2019-04-30-12-23-44
To use the NASA API we need an API key and to get this we need to sign up on their website, and then waiti for the API key to be emailed to us.

Keep your API key safe and do not store it somewhere public, like in a GitHub repo. The API key is linked to your name and any abuse will mean NASA will launch you into space..

The full NASA API can be found here and I am sure that aspiring makers and hackers can use the data for some excellent projects.

Where can I get the code?

If you just want to use my code, then that is cool. All of the code is available from my GitHub repo.

So lets build this project!

Before we write any code we need to install two libraries for the project. These are requests and notify2. Requests is used to get the data from NASA using their API over a typical Internet connection. Notify2 is a Python library to create pop up messages on the Ubuntu desktop. In a terminal type the following to install.

sudo pip3 install requests notify2

With that complete, now open your favourite Python 3 editor and create a new file and then save the file as nasa-pics.py and please do remember to save often!

Python code starts here!

The first line in the Python code is an instruction to Ubuntu to advise it where to find the Python 3 interpreter which will run our code.

#! /usr/bin/env python3

Now lets import the requests and notify2 libraries.

import requests
import notify2

We then initialise notify2 and give the task a title, we never see this but it is handy to have for debug.

notify2.init("NASA Astronomy Picture of the Day")

In order to get the data from NASA we need to know where to look, and as we are interested in their "Astronomy Picture of the Day" we need to go there, but we also need to tell NASA who we are! For that we use the API key that we received via email. Here we create a variable called url and store the web address of the data, and the API key (remember to replace YOUR API KEY HERE with your real API key.

url = "https://api.nasa.gov/planetary/apod?api_key=YOUR API KEY HERE"

Now lets use requests to go to the url and get the raw data from the site. We shall then store it in an object called r

r = requests.get(url)

We then use a conditional test that will check to see if we get anything from NASA. If r has something then the code for that condition will run.

if r:

So lets assume that we have some data from NASA! We need to get the url for that days image, and then store it in a variable called APOD. For this we use r.json()['url'] to search the JSON data for the key url.

    APOD = r.json()['url']

Key?
Screenshot-from-2019-04-30-13-11-59
In Python dictionaries and JSON, data is stored in a key, value relationship. For example here we create a dictionary called food and in there we create a key called Greggs and when we search for that key it returns what Greggs is famous for Sausage rolls

food = {"Greggs":"Sausage roll"}
print(food["Greggs"])

Will print...
Sausage roll

Another variable, this one is called pic and it will store the downloaded image from NASA. It gets the APOD url for us and we set an extra argument to allow_redirects which means that if the web page redirects us to the image we will follow the redirect to that location.

    pic = requests.get(APOD, allow_redirects=True)

We now enter in to another conditional test and this test checks to see if the file is a jpg image. So it looks for the text jpg in APOD and if it is not there it will create a pop up notification on the Ubuntu desktop using notify2

    if  "jpg" not in APOD:
        n = notify2.Notification("No image for today, must be a YouTube video")
        n.show()

Why am I checking this? Well on April 28th the APOD was a YouTube video which broke my code!

If jpg is found in the file then the else condition activates. We open a file at /home/les/Pictures/APOD.jpg and then set it to writable. We then write the contents of pic pic.content to the file. Lastly for this condition it will show a pop up notification to inform us that the image has been changed and that we should enjoy it. Obviously change les to match the name of your account, unless you are called Les.

    else:
        open('/home/les/Pictures/APOD.jpg', 'wb').write(pic.content)
        n = notify2.Notification("Enjoy todays image")
        n.show()

The very last two lines of code are for the original if r: conditional test. It relates to if there is no data in the r object. If it is empty then the code will stop and print "Error"

else:
    print("Error")

Complete code listing

#! /usr/bin/env python3
import requests
import notify2
notify2.init("NASA Astronomy Picture of the Day")
url = "https://api.nasa.gov/planetary/apod?api_key=YOUR API KEY HERE"
r = requests.get(url)
if r:
    APOD = r.json()['url']
    pic = requests.get(APOD, allow_redirects=True)
    if  "jpg" not in APOD:
        n = notify2.Notification("No image for today, must be a YouTube video")
        n.show()
    else:
        open('/home/les/Pictures/APOD.jpg', 'wb').write(pic.content)
        n = notify2.Notification("Enjoy todays image")
        n.show()
else:
    print("Error")

Save your code, but before you run the code we need to create a file called APOD.jpg in our Pictures directory.
Screenshot-from-2019-04-30-14-16-08
You can download an image and rename it APOD.jpg our you can make your own in GIMP etc. What is important is that there is an image in there as we need if for the next step.

Set the desktop background

Right click on the desktop and select Change Background and then change the background to the APOD.jpg in Pictures.

Run the code

Screenshot-from-2019-04-30-14-36-27
To run our code we need to first make nasa-pics.py file executable. So using the file manager, go to the location of the file, right click and select Properties then in Permissions tick Execute to allow executing files as program.

To run the code, open a terminal in the same location as the file and type

./nasa-pics.py

You should see the background change to the latest image.

But what if you want it to run everyday?

In Ubuntu we can add our code to a list of applications that will open when the desktop starts. Search for Startup and you will see the app appear. Click on it and complete the details.
Screenshot-from-2019-04-30-15-03-57

Close the dialog boxes and now every time you reboot, power up the computer it will check to see if there is a new image.

So there we have it!

We've used the NASA API to create our own desktop background changing app using a little Python code!

Happy Hacking!

Bonus Content - Windows 10 Version!

Windows-Code
I promised this the other day, and here it is!
For this version of the code we do not have any pop up notifications, so Notify2 has gone. I did try to make it work with Win10Toaster but it would not find an installation candidate via pip. Shame! But we now have a new library called ctypes that enables us to make changes to DLL files in Windows, such as our default desktop wallpaper!

So the first part of the code now looks like this.

import requests
import ctypes
url = "https://api.nasa.gov/planetary/apod?api_key=YOUR API KEY HERE"
r = requests.get(url)

The next bit remains the same as the original code.

if r:
    APOD = r.json()['url']
    pic = requests.get(APOD, allow_redirects=True)
    if  "jpg" not in APOD:
        print("No image")
    else:

Now we have a slight change to opening a file called APOD.jpg, and then saving the image to that file. You will see that I have saved the image to my Pictures folder, so obviously change this to match your chosen location. Oh and make sure that you use \\ when specifying the absolute location, otherwise Python will throw an error!

        open('C:\\Users\\les\\Pictures\\APOD.jpg', 'wb').write(pic.content)

In the next line we use ctypes to change the wallpaper to the file that we have just downloaded.

        ctypes.windll.user32.SystemParametersInfoW(20, 0, "C:\\Users\\les\\Pictures\\APOD.jpg" , 0)

The remaining code remains as it was.

        print("DONE")
else:
    print("Error")

Complete Code Listing for Windows

import requests
import ctypes
url = "https://api.nasa.gov/planetary/apod?api_key=YOUR API KEY HERE"
r = requests.get(url)
if r:
    APOD = r.json()['url']
    pic = requests.get(APOD, allow_redirects=True)
    if  "jpg" not in APOD:
        print("No image")
    else:
        open('C:\\Users\\les\\Pictures\\APOD.jpg', 'wb').write(pic.content)
        ctypes.windll.user32.SystemParametersInfoW(20, 0, "C:\\Users\\les\\Pictures\\APOD.jpg" , 0)
        print("DONE")
else:
    print("Error")

Run the code

To run the code, you need to have Python 3 installed on your Windows PC. Then you can simply double click on the file to run!

Happy Hacking!