thomaspaulin.me

It's A Bird! It's A Plane! Displaying Live Flight Information Using deck.gl

As part of another project I wished to render data points on a map in real-time, or as near to real-time as possible. Being new to deck.gl this seemed an opportune time to reduce the scope and focusing on rendering.

For this project, I’ve chosen flight data because I’m a fan of anything aerospace. The OpenSky Network API provides a free API for live flight information (for research and non-commercial purposes). I wanted to use Earth observation data for this project, but that data is not real-time thanks to orbital periods.

Information about the data provided by The OpenSky Network API can be found on their documentation. We will receive descriptive and positional information derived from ADS-B and Mode-S transponder messages. Using this information we can render the flight on a map.

The Cast

  • deck.gl - used to render data on the map
  • Mapbox GL JS - used to render the map itself. Provided by the deck.gl examples
  • The OpenSky Network API - provides the flight information
  • Webpack - to bundles everything nicely and provides a better developer experience
  • npm - for package management
  • webpack-dev-server package - to run a local server and verify the results by eye. Provided by the deck.gl examples
  • Javascript - for writing the code. Typescript takes extra setup which is unnecessary for our purposes

In the beginning, there was nothing, no code, no frameworks, just a blank directory staring back at us. To fix this we clone the deck.gl repository. We will be working from the Mapbox directory (/examples/get-started/pure-js/mapbox/).

Next, it’s time to fetch our dependencies using npm install.

Once complete you should be able to run npm start and see this:

The deck.gl Mapbox example up and running

The Mapbox getting started example

Your app.js file should look something like this:

According to the deck.gl documentation “Layer updates happen when the layer is first created, or when some layer props change.” Thus, we must have our live data cause a prop change when it is received. The obvious first step here is a callback that creates the layers arrays using the new data. It then sets the props of the Deck using those layers. Be wary of the performance implications that changing data can bring. We won’t be addressing those in this article.

Now we have a way to set the props from a callback we can fetch flight information from the OpenSky Network API. As a demonstration project, we only care about the latest information for all flights. Thus, we will get network’s entire state vector set, without authenticating. This means our request is: GET https://opensky-network.org/api/states/all.

The response we receive is not in the format deck.gl expects, and so we’ll need to transform it. Fortunately, the OpenSky Network API response is easy to handle meaning a simple mapping function is sufficient.

Once we’ve added this mapping into the response chain we also call the same render(...) function we created earlier. After running, we should see the flights rendered on the map.

Flights plotted on the map using information from the OpenSky Network API

Flight information from the OpenSky Network API rendered

Notes

  • The webpack.config.js file says the local development overrides should be removed from the file. I haven’t had an issue with this so for now they can stay. If you wish to remove them, changing the final line to module.exports = env => CONFIG; should suffice.
  • The deck.gl example works out of the box, but in case you don’t see the map, you should set the Mapbox token. See the comment in the first code snippet for how to do this.
  • We don’t do any checks that the data is the latest, nor do we add any ’thread safety’. It’s possible callbacks arrive out of order and our data ‘goes back in time’.
  • Visit the layer lifecycle page to learn more about how the lifecycles work.