Flight Historian 2.1
Import Flights from Digital Boarding Passes

Release Date
  • 29 Apr 2017 (over 1 year ago)
Repository
Specification

In general, my Flight Historian has been a big time saver for me as far as tracking my flights – instead of manually generating reports and maps from an Excel file, I can simply add flights to a database and let it do all the work. However, as I’ve started tracking more details about my flights over time, the task of entering the flights has become less simple.

Screenshot of New Flight page
There are currently 24 fields to fill out in the flight log. Not every field is required, but it can still take several minutes to fill out a flight.

Since I’d been working on parsing boarding pass barcode data, it seemed like a logical next step to write some sort of scanner that would read a boarding pass barcode and import the data as a new flight. Then one of my Twitter followers had a suggestion:

that's actually not a bad idea. You could import the .xpass format used for apple's wallet make the process easier

— Marco Polo (@TheMarcotto) December 1, 2016

Getting Flight Data from an Apple Wallet Pass

Apple Wallet is an application included with recent iPhones that, among other things, can be used to store boarding passes from various airlines in a single location.

Screenshot of digital boarding pass

Even more importantly, Wallet lets you share boarding passes by email.

Screenshot of Apple Wallet
Screenshot of Apple Wallet

So I decided I’d do for boarding passes what sites like TripIt do for itineraries. I would set up an email address that I could simply email my Wallet boarding passes to, and then have my server look for emails from me and process any boarding pass attachments.

Getting Boarding Passes from IMAP

As the boarding pass email address I set up supports IMAP, I used Ruby’s Net::IMAP class to have Flight Historian interact with my email account.

When I go to the Import Boarding Pass page on Flight Historian, it checks for new messages (from a specified list of my email addresses) which have a “PKPass” (PassKit Package) attachment.

The PKPass format is how Wallet stores and shares digital boarding passes. It’s actually a zipped file archive with the extension .pkpass. Inside this archive is, among other things, a file called pass.json which contains all of the information about the pass in JSON format, including the visible text and the data encoded in the 2- D barcode.

Thus, I wrote a BoardingPassEmail module for Flight Historian which would loop through any email attachments, and for each attachment, unzip it, navigate to pass.json, and store it as a PKPass object in my database. Once Flight Historian successfully saves the pass, it deletes the email that the pass came from.

Adding a Flight from a Stored Boarding Pass

Since flights need to be part of a trip, every View Trip page provides a link to my new Import Boarding Pass view with the Trip’s ID as an argument. However, I included the ability to select a different trip to accept the new flight, if necessary.

Screenshot of Import Boarding Passes page

The “Create Flight” links to the same New Flight form as before, but includes a PKPass ID as an argument. If that pass ID is present, the Flights controller knows that it needs to read the JSON data associated with that pass, and use it to populate the appropriate form fields, saving a great deal of manual data entry.

Screenshot of New Flight page with form fields automatically filled in
Fields which were automatically populated are highlighted so that they can be checked for accuracy.

There are three sources for filling in the the fields:

When the new flight is saved, it also includes a pass_serial_number field, which is a string uniquely identifying each boarding pass as defined in the PKPass format. This way, if a boarding pass is updated, Flight Historian knows that the updated pass needs to be associated with an existing flight rather than a new flight.

Updating a Flight

If Flight Historian finds a boarding pass attachment with a serial number that is already associated with a saved Flight, it shows the pass in a “Flights with Updated Passes” list instead.

Screenshot of Import Boarding Passes page

This time, since the Flight already exists, the form only shows the values which have changed, and allows the user to select the new value or keep the existing value.

Screenshot of Update Flight with New Boarding Pass page
In this case, I was upgraded after I received my first boarding pass, so the new boarding pass updates my travel class and barcode data (since the barcode contains seat number).

Aircraft Types

My flight log previously kept track of aircraft families (e.g. any Boeing 737), and didn’t do anything with specific types (e.g. Boeing 737-800), other than to optionally note them in an aircraft variant text field. This was a deliberate decision, as my flight log was generally set up to catalog my flight experiences, and there was no substantial quality of flight difference for me between, say, a 737-800 and a 737-900.

However, one of the fields I needed to look up on FlightXML was the aircraft type. FlightXML does return the specific aircraft type (by ICAO code), so at the very least, I needed to write a lookup function to convert specific aircraft types into the general aircraft families I was using.

However, I decided that it would make more sense to do it right, and actually incorporate aircraft types into my database. I still wanted to maintain my aircraft family structure, and I still had some old flights in my database that I didn’t know the type for anyway. So I eventually decided to add a parent/child relationship to my Aircraft Families table, where both types and families would be stored in the table (and I could assign a flight either a family or a specific type), but the aircraft types would have a parent_id field that linked to the ID of their parent family. That way, I could still summarize all of my flights by their parent family (by looking at all aircraft types that were part of the given family), and for each specific type FlightXML returned, I would know the family.

The side benefit of this structure is that it also made it easy for me to show statistics for the specific types. Each aircraft family page still includes all the flights it did before, but it also shows a list of types, and clicking on one of those types provides details for that type.

Screenshot of Show Aircraft Family page
Data for all Boeing 737 aircraft I’ve flown
Screenshot of Show Aircraft Type page
Data specifically for Boeing 737-800 aircraft I’ve flown

Change Log

Front End

Back End