Heads-up on Iridium flares

Iridium flares are momentary bright reflections of sunlight off the polished antennae of the Iridium satellites. They can be as bright as magnitude -8 and last as long as a few seconds. There’s usually a good one every few days, and they’re fun to go out and see on clear nights—even more fun if you go out with your kids. Predictions of the time and position of up to a week’s worth of flares (and of other satellite crossings) are available at Heavens Above. To make the most of Heavens Above, you should create an account and have it save your latitude and longitude.

While it’s nice to be able to go to Heavens Above and look up the next set of flares, I thought it would be even better to have the information sent to me. Heavens Above doesn’t have an alert service, so I decided to make one of my own, scraping the information off its page and emailing it to me once a week.

The bulk of the work is done by this script, which I call iridium.py. It uses the Python mechanize module to automate the login procedure, grab the table of data from the Iridium flares web page, wrap that table in some HTML and CSS, and set up mail header that sendmail understands.

 1:  #!/usr/bin/env python
 3:  import mechanize
 4:  from time import strftime
 6:  # Card and email information.
 7:  mailFrom = 'drdrang@gmail.com'
 8:  mailTo = 'drdrang@gmail.com'
 9:  user = {'name' : 'username',  'password' : 'seekret'}
11:  # The URLs for heavens-above.com.
12:  # Login
13:  lURL = 'http://heavens-above.com/logon.asp'
14:  # Iridium flares for next 7 days. Need to add session id after login.
15:  iURL = 'http://heavens-above.com/iridium.asp?Dur=7&Session='
18:  # Create virtual browser and login.
19:  br = mechanize.Browser()
20:  br.set_handle_robots(False)
21:  br.open(lURL)
22:  br.select_form(nr=0)    # the login form is the first on the page
23:  br['UserName'] = user['name']
24:  br['Password'] = user['password']
25:  resp = br.submit()
27:  # Get session ID from the end of the response URL.
28:  sid = resp.geturl().split('=')[1]
30:  # Get the 7-day Iridium page.
31:  iHtml = br.open(iURL + sid).read()
33:  # Extract the table of flare times and magnitudes.
34:  table = iHtml.split(r'<table BORDER CELLPADDING=5>')[1]
35:  table = table.split(r'</table>')[0]
37:  # The links in the table are relative. Turn them into absolute URLs.
38:  table = table.replace('href="', 'href="http://heavens-above.com/')
39:  table = table.replace('HREF="', 'href="http://heavens-above.com/')
41:  # Templates for the email.
42:  mailHeader = '''From: %s
43:  To: %s
44:  Subject: Iridium flares
45:  Content-Type: text/html
46:  '''
48:  pageTemplate = '''<html>
49:  <head>
50:  <style type="text/css">
51:  body {
52:    font-family: Helvetica, Sans-serif;
53:  }
54:  h1 {
55:    font-size: 150%%;
56:    margin-top: 1.5em;
57:    margin-bottom: .25em;
58:  }
59:  table {
60:    border-collapse: collapse; 
61:  }
62:  table th {
63:    padding: .5em 1em .25em 1em;
64:    background-color: #ddd;
65:    border: 1px solid black;
66:    border-bottom: 2px solid black;
67:  }
68:  table tr.due {
69:    background-color: #fcc;
70:  }
71:  table td {
72:    padding: .25em 1em .25em 1em;
73:    border: 1px solid black;
74:  }
75:  </style>
76:  </head>
77:  <body>
78:  <p>For the week of %s</p>
79:  <table>
80:  %s
81:  </table>
82:  </body>
83:  </html>'''
85:  # Construct the html.
86:  html = pageTemplate % (strftime('%b %d, %Y'), table)
88:  # Print out the email header and contents. This should be piped to sendmail.
89:  print mailHeader % (mailFrom, mailTo)
90:  print html

Lines 6–9 customize the script for a particular user. You’ll want to change the email addresses and the Heavens Above username and password. Lines 18–25 create a virtual browser and log in to the site. The site responds by sending the browser to the site’s home page, but with a special session ID string appended to the URL. We grab that session ID for our subsequent browsing.

Lines 30–39 open the Iridium page, extract the data table, and convert all the relative URLs in the table’s links to absolute URLs. This is the sort of thing I would normally do with the Beautiful Soup parsing library, but for some reason, Beautiful Soup chokes on the Heavens Above HTML. So I just did a couple of straightforward splits on the HTML to isolate the data table.

The rest of the script consists of the HTML wrapper code and the mail headers. To send myself an email with the Iridium flare schedule, I run

python /path/to/iridium.py | /usr/sbin/sendmail -t

and I get a nicely formatted email of the schedule, which looks like this in Mail.app

and like this on the iPhone

The table is a little wide for the iPhone, even in landscape mode, but it’s easy enough to read and the links work.

There are several ways to use this code. As it stands, I’ll use Lingon to set up a launchd process that runs the above command every Monday morning and sends me the schedule for the upcoming week. But it would be relatively simple to eliminate the mail headers and wrap the HTML with RSS headers to turn it into a news feed. A more substantial modification could search the table for especially bright flares and send an email or targeted Twitter message on those days.