Particle Xenon as an iBeacon.
Particle Xenon as an iBeacon.

iBeacons are Bluetooth Low Energy (BLE) devices used in location awareness applications such as welcoming people as they arrive at an event or broadcasting information to compatible devices at a nearby museum exhibit. The term iBeacon is apple’s implementation of the technology and reportedly, is what they use at their stores to send notifications to iPhone users as they enter/leave the store.

Another great application of iBeacons is general automation using iOS apps such as Shortcuts and Pushcut. Some examples are turning the lights on when you enter the office or running a HomeKit scene when you leave the house. If you want to learn more about it, I’d recommend listening to the Automators podcast by Rosemary Orchard and David Sparks, they really get into the weeds on the subject.

iBeacons can be bought online, but the purpose of this short post is to reuse a BLE capable small microcontroller running CircuitPython as an iBeacon. In my case I’ll be using Particle Xenon device, but this Adafruit Microcontroller would work just fine (or this one).

Microcontroller Setup

The process is very simple, after installing CircuitPython, put the CircuitPython BLE library in the lib folder as shown below.

Microcontroller folder structure.
Microcontroller folder structure.

Then, paste the following code inside the code.py file in the root folder of the microcontroller:

Note: Change the value of the variable device_uuid to whatever you want it to be, just make sure the total number of characters doesn’t change.

import time
from adafruit_ble.beacon import LocationBeacon
from adafruit_ble.uuid import UUID
# Random UUID:
device_uuid = UUID('12341111-1900-1900-3000-123456712345')
#device_company = 0xFFFF
device_company = 0x004c #Apple manufacturer ID?


b = LocationBeacon(device_company, device_uuid, 001, 010, -45)
print('Initializing Advertising...')
b.start()
print('Done.')

while True:
    #pass
    time.sleep(1)

Important note on BLE library

At the time of this writing (June 2020), the CircuitPython BLE library does not support Apple’s implementation of the Location Beacon (i.e. iBeacon), it only supports the Eddystone implementation by Google. Although they are very similar, the Eddystone beacon cannot be used with iOS Shortcuts or Pushcut (yet?). However, at some point in the past the BLE library supported Apple’s implementation, but it was somehow dropped from the last releases. There is already a bug report submitted to get it fixed, but Adafruit people haven’t gotten to update the code yet.

In the meantime, the version of the BLE library supporting Apple’s iBeacon implementation can still be downloaded from here. You’ll have to use a CircuitPython Alpha version too, which you can downloaded from here. I know, it’s a rather convoluted process right now, hopefully this will get sorted out soon.

iOS Setup

On the iOS side, all the heavy lifting is done by Pushcut. It’s a great complement to Apple’s own Shortcuts app as allows the user to run actions or Shortcuts from notifications that may be triggered by a large variety of events, including location triggers. Since app treats iBeacons as locations, we can use our newly built iBeacon to trigger custom automations within iOS or even trigger HomeKit scenes, if available.

Create a new location trigger in the app and select Beacon. You will see the screen below:

Pushcut trigger configuration screen.
Pushcut trigger configuration screen.

Give it a name and enter the value of the device_uuid variable in the CircuitPython code above in the iBeacon UUID field. Tap on Done and save the trigger. That’s it!.

The microcontroller can be powered by a regular USB port, a 5V power supply or even (in the case of the Particle Xenon) by a Li Ion battery, which makes the setup really portable.

Pushcut notification example using Particle Xenon as an iBeacon.
Pushcut notification example using Particle Xenon as an iBeacon.