Whenever free time and clear night skies are present I like to keep an eye out for satellites moving across the sky. This used to mean actually going outside and waiting but now computer programs make it possible to schedule these moments of awe.
This time of year is perfect for spotting the International Space Station and there are dozens of the ISS trackers that would help to do this, but I wanted to make use of the Pi-Stop traffic light for Raspberry Pi from 4tronix - I have been using these at school with students learning Python and Scratch GPIO.
My system uses one traffic light and a Python program that scrapes the position of the ISS from http://api.open-notify.org/iss-now.json, a site which stores position data in the JSON format. The given lattitude and longitude is compared against a specific location on Earth. The lights come on when various conditions are met.
ISS is not within the visible area and will not move into it over the next three minutes.
ISS is not in the visible area, but it will move into it in the next three minutes.
ISS is visible and getting closer to your position.
ISS is visible but is moving away from your position.
###First import various bits that will be needed. import RPi.GPIO as GPIO import time import urllib2 import json import math import datetime ###This program runs on boot, so there is a minute delay here to allow the wifi connection to become active. time.sleep(60) ###Turn warnings off, then turn all lights off. GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) GPIO.setup(22, GPIO.OUT) GPIO.setup(24, GPIO.OUT) GPIO.setup(26, GPIO.OUT) ###Assume ISS not visible and set state to red. state = "red" ###Variables for storing current location. hereLatitude = 52.127813 hereLongitude = -0.214285 ###Set visibility range (about 800 miles in diameter) north = 60 south = 40 west = -18 east = 18 ###Function for scrapping ISS position from open-notify website. def issPosition(n): try: req = urllib2.Request("http://api.open-notify.org/iss-now.json") response = urllib2.urlopen(req) obj = json.loads(response.read()) if n == "lat": return obj['iss_position']['latitude'] elif n == "long": return obj['iss_position']['longitude'] except urllib2.HTTPError, e: print 'HTTPError = ' + str(e.code) except urllib2.URLError, e: print 'URLError = ' + str(e.reason) except httplib.HTTPException, e: print 'HTTPException' except Exception: import traceback print 'generic exception: ' + traceback.format_exc() ###Function for changing colours def changeLight(n): if n == "red": GPIO.output(26,True) GPIO.output(24,False) GPIO.output(22,False) elif n == "redAmber": GPIO.output(26,True) GPIO.output(24,True) GPIO.output(22,False) elif n == "green": GPIO.output(26,False) GPIO.output(24,False) GPIO.output(22,True) elif n == "amber": GPIO.output(26,False) GPIO.output(24,True) GPIO.output(22,False) ###Function to test if ISS is within ranges set earlier. def issPassTest(lat,long): if lat > south and lat < north and long > west and long < east: return True else: return False ###Function to detect if ISS is getting closer def towardsHereTest(): def distanceFromHere(): latDifferenceSquared = math.pow(hereLatitude - issPosition("lat"),2) longDifferenceSquared = math.pow(hereLongitude - issPosition("long"),2) return latDifferenceSquared + longDifferenceSquared firstCheck = distanceFromHere() time.sleep(5) secondCheck = distanceFromHere() print firstCheck print secondCheck if firstCheck > secondCheck: return True else: return False ###Main continuous loop while True: try: if state == "red": changeLight("red") currentLatitude = issPosition("lat") currentLongitude = issPosition("long") time.sleep(10) previousLatitude = currentLatitude previousLongitude = currentLongitude currentLatitude = issPosition("lat") currentLongitude = issPosition("long") differenceLatitude = currentLatitude - previousLatitude differenceLongitude = currentLongitude - previousLongitude ###Is the ISS going to pass over head in the next three minutes? for i in range(18): if issPassTest(currentLatitude, currentLongitude): state = "redAmber" print state print datetime.datetime.now() currentLatitude += differenceLatitude currentLongitude += differenceLongitude print datetime.datetime.now() print "red: ", currentLatitude, " ", currentLongitude elif state == "redAmber": changeLight("redAmber") ###Is it here yet? If so, go green! for i in range(18): time.sleep(10) if issPassTest(issPosition("lat"), issPosition("long")): state = "green" print "green" break elif i == 17: state = "red" print state elif state == "green": changeLight("green") while state == "green": ###Is it still getting closer? When not, go amber! if towardsHereTest(): print "getting closer" else: state = "amber" print "amber -- moving away from here" elif state == "amber": changeLight("amber") while state == "amber": if issPassTest(issPosition("lat"), issPosition("long")): print "amber" time.sleep(10) else: state = "red" print "Red -- see you again soon!" ###If something goes wrong retrieving data, turn all lights off. except: print "Error with the issPosition function" GPIO.output(26,False) GPIO.output(22,False) GPIO.output(24,False) continue
I have this program run on boot by adding this line to the Pi's crontab file:
@reboot python /home/pi/iss.py
The program runs continuously in the background until manually stopped.