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
Great tutorial thanks for posting this, it’s incredible how simple it is with the node packages
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.
Great tutorial, Dave! Thank you for writing it. This was a fun little project. I came across this while reading your Node/Raspberry Pi tutorials.
Thanks for the positive feedback, Gary. Glad you enjoyed the tutorial!