Node.js IoT: Tracking the ISS through the Sky

ISS

We’re back today to embark on another cool Node.js IoT project.  This time, we’re going to interact with the International Space Station (ISS) and track it as it flies through the sky.  We’ll eventually work with physical sensors that sit right on our desk, but at this stage we won’t need to buy parts or read resistor color codes in order to retrieve values from the ISS GPS “sensor” in the cloud—or actually 250 miles above the clouds.

While our tutorials are geared toward creating awesome Node.js IoT projects on the Raspberry Pi, any Node.js-capable machine will suffice for today’s tutorial.  Other useful articles to help you may include my Beginner’s Guide to Installing Node.js on a Raspberry Pi.  You can also see my article on Using Visual Studio Code with a Raspberry Pi if you are in need of a development environment.

Let’s get started and progressively build a solution so we can track the ISS and ultimately monitor its location relative to our location on earth.

Inspect the ISS API

Thankfully the Open Notify project has done a lot of the heavy lifting for us.   Open Notify “is an open source project to provide a simple programming interface for some of NASA’s awesome data”.  We are going to use their ISS Current Location API  (Application Programming Interface) to fetch JSON data we can parse in order to get the current latitude and longitude of the ISS.

Go ahead and launch the ISS Current Location API URL at http://api.open-notify.org/iss-now.json so you can review the JSON data structure that is returned.  It should look something like this:

{
  "iss_position": {
    "latitude": 29.697058039473895, 
    "longitude": 65.91489767955896
  }, 
  "message": "success", 
  "timestamp": 1471022773
}

Beautiful!  We’re ready to write some Node.js code to consume the ISS Web API and specifically retrieve the ISS positional coordinates.  Let’s do this.

Fetch the ISS JSON Data

To get started, create a new folder for your ISS project and navigate to that folder using the terminal.  Next, create a blank package.json file and automatically accept all of the defaults without being prompting by issuing the following command:

$ npm init -y

We are now ready to install got, a fabulous npm module for retrieving web content using JavaScript promises.  We also save got as a dependency in our package.json file at the same time:

$ npm install --save got

Next, create a file called index.js and add the following contents:

const got = require('got');

const url = 'http://api.open-notify.org/iss-now.json';

got(url, { json: true })
  .then(iss => {
    console.log(iss.body);
  })
  .catch(error => {
    console.log(error.response.body);
  });

In this code, we use got to retrieve the JSON from the ISS Web API URL.  The got module returns the entire JSON object using the iss.body property.

Let’s go ahead and invoke index.js and review the results:

$ node index.js
{ iss_position: { latitude: -23.59804745030018, longitude: 108.44302273531916 },
message: 'success',
timestamp: 1471023851 }

We are successfully retrieving the JSON data containing the current ISS position.  This is a great first step!

Capture a Subset of the ISS JSON Data

Let’s next zoom in and retrieve and print the ISS position data to the console without all of the other data contained in the JSON 0bject.  Modify your code as follows:

const got = require('got');

const url = 'http://api.open-notify.org/iss-now.json';

got(url, { json: true })
  .then(iss => {
    const position = iss.body.iss_position;
    console.log(position);
  })
  .catch(error => {
    console.log(error.response.body);
  });

Notice how we utilize a position variable that retrieves the iss.body.iss_position part of the JSON object.  Parsing JSON data is easy in JavaScript since JSON is a valid subset of JavaScript; there’s a reason JSON is so popular for Web APIs there days!  When you invoke the code above, you should see results that look something like this:

$ node index.js
{ latitude: -46.72522165921968, longitude: 143.01017299264683 }

Create a Loop to Continuously Retrieve the Position of the ISS

Following techniques we’ve utilized in previous IoT tutorials, we modify our code to run continuously in a loop so we can watch the position of the ISS change over time:

const got = require('got');

const delaySeconds = 3;
const url = 'http://api.open-notify.org/iss-now.json';

function loop() {
  got(url, { json: true })
    .then(iss => {
      const position = iss.body.iss_position;
      console.log(position);
    })
    .catch(error => {
      console.log(error.response.body);
    });
  setTimeout(loop, delaySeconds * 1000);
}

loop();

We start by running our loop every 3 seconds so we can receive fast feedback as the ISS position changes.  Given that the ISS travels close to 28,000 km/h (17,400 MPH), we should see some change in its latitude and longitude even at these short intervals!

Running this new iteration of your Node.js code should result in output that looks something like this:

$ node index.js
{ latitude: -48.6844921584891, longitude: -161.05846976116362 }
{ latitude: -48.63833715517274, longitude: -160.874846955517 }
{ latitude: -48.59071024609024, longitude: -160.68705773447667 }
{ latitude: -48.5270358075528, longitude: -160.43861643360663 }

Press Ctrl+C to terminate the Node.js loop and return to the command prompt.

Calculate the Distance of the ISS from Your Current Location on Earth

We are now positioned (no pun intended :)) to calculate the distance of the ISS from our current location on earth.  Our choices are to embark on a multi-year mathematical journey learning the finer intricacies of geospatial analysis or leverage an existing npm module to do the heavy lifting.  I’m going to opt for the latter, but you are free to determine your desired path. 🙂

The geolib npm module becomes our BFF (best friend forever) here— or least our best friend until we can declare victory in our current Node.js IoT adventure!  Let’s first install it and save it as a dependency in our package.json file:

$ npm install --save geolib

We will need our current latitude and longitude on earth so we can calculate the distance between us and the ISS.  This is going to be awesome – we are rapidly moving toward our goal!  Venture out to LatLong.net to get the latitude and longitude of your location on earth. My general coordinates in San Diego, California are:

  • Latitude: 32.715738
  • Longitude: -117.161084

Let’s modify our Node.js code to calculate our distance from the ISS:

const got = require('got');
const geolib = require('geolib');

const delaySeconds = 3;
const url = 'http://api.open-notify.org/iss-now.json';
const myPosition = { latitude: 32.715738, longitude: -117.161084 };

function loop() {
  got(url, { json: true })
    .then(iss => {
      const position = iss.body.iss_position;
      const distanceFromIss = geolib.getDistance(myPosition, position);
      console.log(`${distanceFromIss} meters`);
    })
    .catch(error => {
      console.log(error.response.body);
    });
  setTimeout(loop, delaySeconds * 1000);
}

loop();

In the code above, we include the geolib module.  We also specify our current latitude and longitude in the myPosition variable.  Finally, we use the geolib.getDistance function to calculate the distance in meters between our location and the current ISS location.  Geospatial math doesn’t have to be difficult when you are standing on the shoulders of giants. 🙂

Run the program and watch in real-time as the ISS gets closer or further away from you:

$ node index.js
8092126 meters
8110176 meters
8128888 meters
8147272 meters
8165897 meters
8184446 meters
8202998 meters
.....

As a final step, since I live in a country where we grok miles better than meters, we can utilize the geolib.convertUnit function to convert the default units of meters to miles.

const got = require('got');
const geolib = require('geolib');

const delaySeconds = 3;
const url = 'http://api.open-notify.org/iss-now.json';
const myPosition = { latitude: 32.715738, longitude: -117.161084 };

function loop() {
  got(url, { json: true })
    .then(iss => {
      const position = iss.body.iss_position;
      const distanceFromIss = geolib.getDistance(myPosition, position);
      const distanceFromIssMiles = geolib.convertUnit('mi', distanceFromIss, 2);
      console.log(`${distanceFromIssMiles} miles`);
    })
    .catch(error => {
      console.log(error.response.body);
    });
  setTimeout(loop, delaySeconds * 1000);
}

loop();

Invoke the program and view the modified results in miles:

$ node index.js
5390.53 miles
5401.56 miles
5413.21 miles
5424.83 miles
5436.49 miles
5448.15 miles
5459.81 miles
.....

Conclusion

There we have it! We’re created an IoT project to monitor our world and track the current location of the ISS relative to our location. I’ve had fun, and I hope you’ve had fun and learned something too.

Follow @thisDaveJ on Twitter to stay up to date on the latest tutorials and tech articles.

Additional Articles

Beginner’s Guide to Installing Node.js on a Raspberry Pi
Using Visual Studio Code with a Raspberry Pi (Raspbian)
Visual Studio Code Jumpstart for Node.js Developers
Node.js Learning through Making – Build a CPU Sensor

Share

6 thoughts on “Node.js IoT: Tracking the ISS through the Sky

    1. Thanks for the feedback, Mel! I completely agree. There are some amazing node packages out there that are making it simple and enabling all of us to build fun and useful apps.

Leave a Reply

Your email address will not be published. Required fields are marked *