My first attempt at scanning and analyzing iBeacon data was done with Java and Node.js. The Raspberry Pi devices were using Java, and the data was being offloaded to a Node.js server. The problem with this is that Java is too heavy for the low spec Internet of Things (IoT) devices.

Fast forward to round two of playing with iBeacon devices and a Raspberry Pi. We’re going to see how to use Golang to scan for BLE signals and parse the data to determine if they are iBeacon.

This time around, I’m going to be using a Raspberry Pi Zero W instead of a Raspberry Pi 3. These devices are a fraction of the size and a fraction of the price.

Before continuing, you need to have set up the Raspberry Pi Zero W with Raspbian. If you’re not sure how to do this, check out my tutorial titled, Use Your Raspberry Pi as a Headless System Without a Monitor. You can even take this tutorial a step further and learn how to automatically configure your WiFi on the Pi Zero W, here.

Develop a Golang Application on a Host Computer

Golang is great because you can install it pretty much anywhere and run applications built with it pretty much anywhere. However, to save us the burden of slow compile times on a Raspberry Pi Zero W, we’re going to do our development on a host machine like Mac or Windows and cross-compile it.

The above command will download the Gatt (Generic Attribute Profile) library created by PayPal. The Gatt library will do all the heavy lifting when it comes to scanning for Bluetooth Low Energy devices. Most of our work will be in parsing.

Within your $GOPATH, create a new project with a main.go and a ibeacon.go file. We’ll do the parsing in our ibeacon.go file and the scanning in our main.go file.

Let’s start by creating our parsing logic. Open the project’s ibeacon.go file and include the following:

We know our iBeacon will have a UUID as well as a major and minor code. For this reason, we create a data structure for it. Within the NewiBeacon function, we accept manufacturer data and return a parsed iBeacon instance.

The manufacturer data will be passed in from the Gatt scanning. However, once we have the data, we can start parsing it. There are many other types of devices that will be picked up with Gatt, but we can narrow down what is and isn’t an iBeacon.

When the bluetooth state is powered on and ready, we start scanning for all peripherals, allowing duplicates. Remember, iBeacons typically broadcast numerous times per second. If we don’t allow duplicates, not all our discoveries will register.

Fast forward to the most important part of our scanning code, the onPeripheralDiscovered function:

When a BLE device is picked up in our scan, we pass the manufacturer data into our parser. If it is a valid iBeacon, we print out the parsed data.

If you want to upload this data, you could run some HTTP requests instead of printing the data to the screen.

Configuring the Raspberry Pi Zero W for Bluetooth Scanning

Per the Gatt instructions, Gatt needs complete control of your bluetooth. For this reason, we need to disable functionality within the OS.

Sign into your Raspberry Pi Zero W and execute the following commands:

sudo hciconfig hci0 down
sudo service bluetooth stop

The above commands will bring down the bluetooth device and stop the built-in bluetooth server. Don’t worry, if you restart your Pi, they will come back on. You can also start them manually. If you want a more permanent solution, you’ll need to alter the startup scripts.

Building and Deploying the Golang Application

With the code ready to go, we need to compile the application to be used on the Raspberry Pi Zero W. If you’re using a Mac or Windows computer and you try to run this application, there is a pretty good chance it will not work. I have tested this on my Raspberry Pi Zero W and it works flawlessly.

Make sure the change the filename, path, and hostname to whatever yours are. If you’d rather transfer the binary another way, do whatever works for you.

To run the application on your Pi, execute the following:

sudo ./name-of-binary-file

You’ll need to use sudo otherwise your application won’t have access to your BLE functionality. Based on how we wrote our Go application, scanning should happen until we tell it to stop.

Conclusion

You just saw how to scan for BLE iBeacon devices from a Raspberry Pi Zero W using Golang and the open source Gatt library. This guide isn’t limited to just the Pi Zero W. It should work fine on the standard Raspberry Pi or any other computer that has BLE support.

Nic Raboy

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