Our website is made possible by displaying online advertisements to our visitors. Please consider supporting us by disabling your ad blocker.

Use Node.js And A Raspberry Pi Zero W To Scan For BLE iBeacon Devices

TwitterFacebookRedditLinkedInHacker News

Earlier this month I had written a tutorial for detecting nearby BLE iBeacon devices using a Raspberry Pi Zero W and an application written with Golang. It was a great example of accomplishing something with Go and very little code.

Scanning for BLE devices is a great use case for Internet of Things (IoT) devices like the Raspberry Pi Zero W, and Golang isn’t the only great language around. I, like many others, do a lot of Node.js development as well.

We’re going to see how to scan for BLE iBeacon devices using Node.js and the popular Node.js BLE (Noble) library.

If you haven’t already done so, you’ll need Node.js installed on your Pi Zero W. If you’re not sure how to install Node.js on an ARMv6l device, check out my previous tutorial titled, Install Node.js on a Raspberry Pi Zero W without NodeSource.

Installing the Necessary Raspbian Linux Bluetooth Dependencies

If you’re using Raspbian Linux, the necessary dependencies for working with Bluetooth likely aren’t already available. Instead we have to install them.

Use SSH to connect to the Raspberry Pi Zero W and execute the following command:

sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev

The libraries are nothing special to the noble library and are common for using Bluetooth on Linux. In fact, the list came from the noble documentation.

Create a New Node.js Project with the Node Package Manager (NPM)

Going forward, we’re going to assume that all development will happen via the Raspberry Pi Zero W through SSH or something similar. First we’ll need to create a fresh project.

From the CLI, execute the following command:

npm init -y

The above command will create a package.json file, or in other words, a new Node.js project.

To actually scan for BLE iBeacons, we’ll need to install a few packages for our project. From the CLI execute the following commands:

npm install noble --save
npm install node-beacon-scanner --save

The above commands will install the noble package for scanning for BLE devices and the node-beacon-scanner package which parses BLE packets and only works with those classified as beacons. Beacons include iBeacon and Eddystone, but we’re going to focus on iBeacon.

The node-beacon-scanner library is not a requirement, but it does make life easier since you won’t have to manually parse the advertisement data.

If you’re like me, using a Mac for development, you can actually test your code locally before transfering it to the Raspberry Pi Zero W. The catch is that you need to be using a specific version of noble. Instead of using the primary package that was installed previously, you could execute the following:

npm install https://github.com/jacobrosenthal/noble.git#highsierra --save

You can learn more about High Sierra support in an issue ticket on GitHub. However, it is likely to be merged into the primary package at some point. Again, this is only necessary if you wish to test on Mac, not strictly on the Raspberry Pi.

Developing the BLE Scanning Logic with JavaScript and Noble

Now that we have a project created, we can start development. For simplicity, all of our code will exist in a single JavaScript file.

Create a new file in your project called app.js and include the following JavaScript code:

const Noble = require("noble");
const BeaconScanner = require("node-beacon-scanner");

var scanner = new BeaconScanner();

scanner.onadvertisement = (advertisement) => {
    var beacon = advertisement["iBeacon"];
    beacon.rssi = advertisement["rssi"];
    console.log(JSON.stringify(beacon, null, "    "))
};

scanner.startScan().then(() => {
    console.log("Scanning for BLE devices...")  ;
}).catch((error) => {
    console.error(error);
});

While short and simple, the above JavaScript code is quite powerful. To give credit where credit is due, most of it came from the node-beacon-scanner documentation.

So what is happening?

We’re including the previously downloaded libraries, the first which does the heavy lifting and the second which wraps the first to do our advertisement parsing. Once we start scanning, we use our onadvertisement listener to pick up any beacons. Quite a lot of data comes back, but I’ve always found that the RSSI and iBeacon data is what’s useful.

In this example we only plan to print out the iBeacon devices that were discovered. We could easily take the advertisement data and add it to a database like one of my previous examples, or even send push notifications.

Running the Application with Sudo

When we’re ready to start the application and scan for BLE packets, we can’t just run it like we would any ordinary Node.js application. Instead we have to run it with privilege like the following:

sudo node app.js

We need to use sudo because only privileged applications can access Bluetooth functionality on Linux.

Raspberry Pi Node.js iBeacon Scanner

If everything went smooth and you have iBeacon devices broadcasting nearby, the Raspberry Pi Zero W should pick them up and print them out like in the above image.

Conclusion

You just saw how to scan for Bluetooth Low Energy (BLE) iBeacon devices using a Raspberry Pi Zero W and Node.js. You could easily take this tutorial to the standard size Raspberry Pi if you’d like as well, since it also has BLE support.

If you’re curious to know what kind of iBeacon I’m using, I’m using Gimbal beacons because you can pick them up for $5.00 each and configure them to use the iBeacon specification.

Want to accomplish the same BLE scanning with Go? Check out my previous tutorial.

A video version of this article can be seen below.

Nic Raboy

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in C#, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Unity. Nic writes about his development experiences related to making web and mobile development easier to understand.