153

I'd like to create my own iBeacon with some Bluetooth Low Energy dev kits. Apple has yet to release a specification for iBeacons, however, a few hardware developers have reverse Engineered the iBeacon from the AirLocate Sample code and started selling iBeacon dev kits.

So what is the iBeacon Bluetooth Profile?

Bluetooth Low Energy uses GATT for LE profile service discovery. So I think we need to know the Attribute Handle, Attribute Type, Attribute Value, and maybe the Attribute Permissions of the iBeacon attribute. So for an iBeacon with a UUID of E2C56DB5-DFFB-48D2-B060-D0F5A71096E0, a major value of 1 and a minor value of 1 what would the Bluetooth GATT profile service be?

Here are some assumptions I've made from the discussion on Apple's forums and through the docs.

  1. You only need to see the profile service (GATT) of a Bluetooth peripheral to know it is an iBeacon.

  2. The Major and Minor keys are encoded somewhere in this profile service

Heres some companies with iBeacon Dev Kits that seem to have this figure out already:

Hopefully, in time we will have a profile posted on Bluetooth.org like these: https://www.bluetooth.org/en-us/specification/adopted-specifications

Pranav Kasetti
  • 8,770
  • 2
  • 50
  • 71
PaulWoodIII
  • 2,636
  • 7
  • 31
  • 35
  • actually now I've got it down to what 4 attribute values are – PaulWoodIII Sep 23 '13 at 16:45
  • @Dan1One I've replicated the service using Light Blue, then using Apple's AirLocate sample code I could not range the duplicated service I think there is something more, Also Light Blue does not have the Attribute Handle listed – PaulWoodIII Sep 23 '13 at 16:48
  • Are you looking for a way to create an iBeacon with CBPeripheralManager (that runs in the background), or another piece of (non-iOS) software, or hardware? This will lead towards the detail required. – Wain Sep 24 '13 at 07:02
  • @Wain I am trying to put in on my own hardware as the first paragraph notes. But as I noted in the linked question it could potentially be useful to the answer of the linked question using CBPeripheralManager advertising the iBeacon in the background – PaulWoodIII Sep 24 '13 at 07:50
  • ticatag.com provides iBeacon compatible solution – fvisticot Nov 30 '13 at 10:43
  • There's no "reverse engineering" here. The iBeacon fields are available on apple.developer.com. Correlate that with the published Bluetooth spec and it's there in plain view. – Bogdan Alexandru Jun 29 '16 at 11:38
  • 1
    Great! can you share that documentation here for future programmers, when I asked the question in 2013 it definitely did not exist yet – PaulWoodIII Jul 21 '16 at 21:15

6 Answers6

231

For an iBeacon with ProximityUUID E2C56DB5-DFFB-48D2-B060-D0F5A71096E0, major 0, minor 0, and calibrated Tx Power of -59 RSSI, the transmitted BLE advertisement packet looks like this:

d6 be 89 8e 40 24 05 a2 17 6e 3d 71 02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 52 ab 8d 38 a5

This packet can be broken down as follows:

d6 be 89 8e # Access address for advertising data (this is always the same fixed value)
40 # Advertising Channel PDU Header byte 0.  Contains: (type = 0), (tx add = 1), (rx add = 0)
24 # Advertising Channel PDU Header byte 1.  Contains:  (length = total bytes of the advertising payload + 6 bytes for the BLE mac address.)
05 a2 17 6e 3d 71 # Bluetooth Mac address (note this is a spoofed address)
02 01 1a 1a ff 4c 00 02 15 e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 00 00 00 00 c5 # Bluetooth advertisement
52 ab 8d 38 a5 # checksum

The key part of that packet is the Bluetooth Advertisement, which can be broken down like this:

02 # Number of bytes that follow in first AD structure
01 # Flags AD type
1A # Flags value 0x1A = 000011010  
   bit 0 (OFF) LE Limited Discoverable Mode
   bit 1 (ON) LE General Discoverable Mode
   bit 2 (OFF) BR/EDR Not Supported
   bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
   bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
1A # Number of bytes that follow in second (and last) AD structure
FF # Manufacturer specific data AD type
4C 00 # Company identifier code (0x004C == Apple)
02 # Byte 0 of iBeacon advertisement indicator
15 # Byte 1 of iBeacon advertisement indicator
e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon proximity uuid
00 00 # major 
00 00 # minor 
c5 # The 2's complement of the calibrated Tx Power

Any Bluetooth LE device that can be configured to send a specific advertisement can generate the above packet. I have configured a Linux computer using Bluez to send this advertisement, and iOS7 devices running Apple's AirLocate test code pick it up as an iBeacon with the fields specified above. See: Use BlueZ Stack As A Peripheral (Advertiser)

This blog has full details about the reverse engineering process.

davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • This is great! Exactly what I was searching for. But could anybody explain how I can compute the checksum? – Benjamin Groener Oct 04 '13 at 15:27
  • I've got another question for you to help us complete the spec a little more. What seems to be the correct broadcast interval in ms? I'm noticing using the texas instruments code I'm using as a basis for my iBeacon makes apple's Airlocate app act kind of inconsistent when displaying a list of nearby iBeacons. – PaulWoodIII Oct 28 '13 at 10:32
  • Is the UUID / proximityUUID a BLE profile specific to iBeacon or is it up to the device manufacturer? What is the preferred method for distinguishing between iBeacon devices: The BT MAC address, the UUID or the major / minor values? – nickaknudson Nov 15 '13 at 02:46
  • David, have you been able to configure an iOS device with a specific advertisement packet when using the Core Bluetooth GATT APIs? I couldn't find the option. You can define custom UUIDs for Services and Characteristics but not for the advertisement. – miguel Nov 26 '13 at 04:04
  • Sure, CLBeaconRegion even gives you a helper to construct the advertisement definition. Just pass [CLBeaconRegion peripheralDataWithMeasuredPower:] to [CBPeripheralManager startAdvertising:] – davidgyoung Nov 26 '13 at 19:35
  • As the specs says, there is the Access Address specified to the physical channels, so why is it fixed in the case of advertising channels, while we have 3 adv channels? I'm confused about this. – user2423804 Aug 07 '14 at 06:19
  • What does "AD" stand for in the response? – Reinaldo Junior Oct 16 '14 at 02:45
  • 1
    @ReinaldoJunior AD = Advertising Data. See references in answer by slackhappy. – RenniePet May 21 '15 at 22:56
  • My fiddling with these devices seems to indicate that the company code is in little-endian while the major and minor ids are in big-endian. If this is correct it would be an advantage if that was mentioned in the answer, where the various fields are listed. – RenniePet May 30 '15 at 06:19
  • Correct. I have added endianness notes. – davidgyoung May 30 '15 at 13:22
  • @davidgyoung Hi, can you tell me how you ended up having 5 bytes for CRC value? According to the spec BLE uses CRC-24 so it's supposed to be 3 bytes there. What am I missing? – dr.doom Feb 27 '16 at 04:32
  • There are two CRCs, the hardware CRC is three bytes as you say. But a second 2 byte CRC is inside of it. – davidgyoung Feb 28 '16 at 02:12
  • Sorry to insist and probably becoming a pain but is that part of the BLE spec or an iBeacon feature? By the sound of it "two CRCs" I assume that the outer CRC is for the entire packet and the inner 2 byte CRC is for the iBeacon specific AD Structure(?). Maybe I wasn't looking very carefully but I haven't seen anything related to that in the spec. Can you provide any pointers? Also isn't preamble part of the packet? – dr.doom Feb 28 '16 at 03:56
  • Why do you suggest using 1a for the AD flags? In particular, this sets the 'LE General Discoverable Mode'. To quote the iBeacon spec: "All accessories that support the Proximity Beacon Feature must [...] and implement the Broadcaster role a defined in the Bluetooth Core specification". To quote the Bluetooth specification: "A device in the Broadcaster role shall not set the 'LE General Discoverable Mode' flag or the 'LE Limited Discoverable Mode'." Surely this is inconsistent with these specifications? – Alex Coplan Aug 08 '16 at 16:11
  • Understand that I am not "suggesting" using 1A -- I am just reporting what the reference implementation transmitted when I scanned the packet. Whether it is wise or consistent with various specs is a different story. – davidgyoung Aug 08 '16 at 19:50
47

It seems to based on advertisement data, particularly the manufacturer data:

4C00 02 15 585CDE931B0142CC9A1325009BEDC65E 0000 0000 C5

<company identifier (2 bytes)> <type (1 byte)> <data length (1 byte)>
    <uuid (16 bytes)> <major (2 bytes)> <minor (2 bytes)> <RSSI @ 1m>
  • Apple Company Identifier (Little Endian), 0x004c
  • data type, 0x02 => iBeacon
  • data length, 0x15 = 21
  • uuid: 585CDE931B0142CC9A1325009BEDC65E
  • major: 0000
  • minor: 0000
  • meaured power at 1 meter: 0xc5 = -59

I have this node.js script working on Linux with the sample AirLocate app example.

Muhammad Adnan
  • 2,668
  • 15
  • 27
sandeepmistry
  • 2,058
  • 4
  • 20
  • 25
  • Sadly the script is not available anymore. Would you mind sharing it again? – Thomaschaaf Mar 11 '14 at 07:39
  • @Thomaschaaf sorry I removed here is a [link](https://github.com/sandeepmistry/node-bleacon/blob/51eadf0ad3c17e2b0687a4ca220f0fefc697b05e/linux-ibeacon.js) to the old version in Github. I've also updated [bleacon](https://github.com/sandeepmistry/node-bleacon) to not require spawning hcitool/hciconfig. – sandeepmistry Mar 11 '14 at 18:15
  • "meaured power at 1 meter: 0xc5 = -59" how do you calcuate from 0xc5 to -59? – andreasbecker.de Jul 16 '14 at 09:01
  • @andreasbecker.de you take the [two's complement](http://en.wikipedia.org/wiki/Two's_complement) – sandeepmistry Jul 16 '14 at 15:44
  • @sandeepmistry the link to node.js script is now broken. – tedyyu Jul 18 '15 at 12:37
  • @tedyyu updated link: https://github.com/sandeepmistry/node-bleacon/blob/master/test.js - for previous version see: https://github.com/sandeepmistry/node-bleacon/blob/78898852d00e712f1e897e0a5f360534b1a6c87f/linux-ibeacon.js – sandeepmistry Jul 19 '15 at 13:31
20

Just to reconcile the difference between sandeepmistry's answer and davidgyoung's answer:

02 01 1a 1a ff 4C 00

Is part of the advertising data format specification [1]

  02 # length of following AD structure
  01 # <<Flags>> AD Structure [2]
  1a # read as b00011010. 
     # In this case, LE General Discoverable,
     # and simultaneous BR/EDR but this may vary by device!

  1a # length of following AD structure
  FF # Manufacturer specific data [3]
4C00 # Apple Inc [4]
0215 # ?? some 2-byte header

Missing from the AD is a Service [5] definition. I think the iBeacon protocol itself has no relationship to the GATT and standard service discovery. If you download RedBearLab's iBeacon program, you'll see that they happen to use the GATT for configuring the advertisement parameters, but this seems to be specific to their implementation, and not part of the spec. The AirLocate program doesn't seem to use the GATT for configuration, for instance, according to LightBlue and or other similar programs I tried.

References:

  1. Core Bluetooth Spec v4, Vol 3, Part C, 11
  2. Vol 3, Part C, 18.1
  3. Vol 3, Part C, 18.11
  4. https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers
  5. Vol 3, Part C, 18.2
slackhappy
  • 201
  • 1
  • 3
  • Thanks @slackhappy, I've updated my answer. The 2 byte header is 0x02 data type, 0x15 = 21 data length. – sandeepmistry Oct 05 '13 at 12:36
  • thanks @slackhappy this is good, but can I ask a dumb question? If I wanted to send out some message like "Come in for a free coffee" or something like that, would I just replace the `FF` in your example with the HEX value of my string? (and also update the length of the AD structure to suite?) – Mark Dec 18 '13 at 02:31
6

If the reason you ask this question is because you want to use Core Bluetooth to advertise as an iBeacon rather than using the standard API, you can easily do so by advertising an NSDictionary such as:

{
    kCBAdvDataAppleBeaconKey = <a7c4c5fa a8dd4ba1 b9a8a240 584f02d3 00040fa0 c5>;
}

See this answer for more information.

Community
  • 1
  • 1
Senseful
  • 86,719
  • 67
  • 308
  • 465
4

It’s very simple, it just advertises a string which contains a few characters conforming to Apple’s iBeacon standard.

Dharman
  • 30,962
  • 25
  • 85
  • 135
0

iBeacon Profile contains 31 Bytes which includes the followings

  1. Prefix - 9 Bytes - which include s the adv data and Manufacturer data
  2. UUID - 16 Bytes
  3. Major - 2 Bytes
  4. Minor - 2 Bytes
  5. TxPower - 1 Byte

enter image description here

AmbiBala
  • 69
  • 6