iBeacons – Let your Mac broadcasts

iBeacons are built on top of Core Bluetooth so I wondered whether it would be possible to use a MacBook running Mavericks to create an iBeacon transmitter. As iBeacon is just the name Apple gives for using Bluetooth 4.0 Advertising mode with a specific data format. So transmitting iBeacons should not be very difficult.
A Bluetooth 4.0 Advertising packet consist of the following information:

  • Preamble – 1 byte. Always 0xAA
  • Access Address: 4 bytes. Always 0x8E89BED6
  • CRC: 3 bytes checksum calculated over PDU
  • PDU (Protocol Data Unit): 39 bytes

The first three parts of the packet are handled by the Bluetooth Stack, so we should care about what information it is being sent in the Protocol Data Unit. Inside PDU there are some fields reserved for information, including Advertising channel, Manufacturer Specific Information, and so on. But the last 4 fields are of our interest. They are:

  1. Transmitter UUID (16 bytes)
  2. Major number (16 bit uint)
  3. Minor number (16 bit uint)
  4. Measured power (1 byte encoded as U2)

Major and Minor numbers help us differentiate between transmitters with the same UUID.
Matthew Robinson created an app for OSX called BeaconOSX that uses Mac’s Bluetooth 4.0 to transmit iBeacons, and a very simple class where it is easy to see how to encode information into the PDU and broadcast it.

- (NSDictionary *)beaconAdvertisement {

NSString *beaconKey = @”kCBAdvDataAppleBeaconKey”;
unsigned char advertisementBytes[21] = {0};
[self.proximityUUID getUUIDBytes:(unsigned char *)&advertisementBytes];
advertisementBytes[16] = (unsigned char)(self.major >> 8);
advertisementBytes[17] = (unsigned char)(self.major & 255);
advertisementBytes[18] = (unsigned char)(self.minor >> 8);
advertisementBytes[19] = (unsigned char)(self.minor & 255);
advertisementBytes[20] = self.measuredPower;
NSMutableData *advertisement = [NSMutableData dataWithBytes:advertisementBytes length:21];
return [NSDictionary dictionaryWithObject:advertisement forKey:beaconKey];

-(void)startAdvertising {

_manager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
NSDictionary* beaconAdvertisement = [self beaconAdvertisement]
[_manager startAdvertising:beaconAdvertisement];
More information about Bluetooth Advertising mode can be found at: https://www.bluetooth.org/en-us/specification/adopted-specifications