First of all, let’s make it clear that the Bluetooth broadcast package we get from the SDK in Android is a 62-byte array that has been processed by the underlying SDK. Where does this 62-byte array come from?

To figure out this problem, first of all, we need to know what is the original broadcast packet sent by iBeacon?

First of all, let’s be clear, bluetooth sends out data in two parts: a regular broadcast packet and what’s called a reply packet. This is the stipulation of Bluetooth protocol for all Bluetooth devices (iBeacon is only one kind of Bluetooth device).

  • The normal broadcast packet format is defined and has a length of30 byte
  • The contents of the reply packet can be put into it by the bluetooth manufacturers themselves. The maximum length is32 byte

Note that the received data is sent from the lowest to the highest level at one time. Therefore, the received data must be returned to be combined by bytes. For example, if the received MAC address is 8B 03 00 B0 01 C2, the actual MAC address is C2:01: B0:00:03:8B

Bluetooth broadcast packet

Let’s start with the first Bluetooth broadcast packet (from the iBeacon device), which is 59 bytes long

04 3E 38 0D 01 13 00 01 8B 03 00 B0 01 C2 01 00 FF 7F AF 00 00 00 00 00 00 00 00 00 00 1E 29 bytes 02 01 06 1A FF 4C 00 02 15 Fd a5 06 93 A4 e2 4f b1 af cf c6 eb 07 64 78 25 27 11 4c b9 c5 30 bytesCopy the code

The content in the first line can be considered as the attached information in the Bluetooth broadcast package, which cannot be seen through the Android SDK. The second line is the previous part of the broadcast package we received in the Android SDK.

The first byte is HCI Packet Type, 04 means this is an HCI Event; The remaining 58bytes are HCI Event details. The second byte is EventCode, and 3e is the code for the Event. The third byte is Parameter Length, 0x38(decimal 56) indicates the following data Length of 56bytes. The fourth byte is SubEvent, 0d indicates that this is LE Extended Advertising Report. The fifth byte is Num Reports, and the value is 01, 1B, 00. These two bytes represent the Event Type. Since the data is sent in bytes and from low to high, So the true value is 001b. 01 indicates that this is a random device address. 8B 03 00 B0 01 C2 is the MAC address of the device. So the real MAC is c2:01:b0:00:03:8b 01 represents the bandwidth of the primary broadcast channel 00 represents the bandwidth of the secondary broadcast channel, where the secondary channel is not used ff represents the broadcast SID 7f represents the size of Tx Power and 127dbm af represents the size of RSSI. 00 00 indicates the direct address type. The frequency is the common device address. 00 00 00 indicates the direct BD_ADDR 1e indicates the number of bytes (length) of the next dataCopy the code

The above content is the explanation corresponding to the first line. In fact, the Android SDK has helped us to parse out part of the content of these data, and we can directly obtain it through the corresponding SDK method.

Now let’s look at broadcast packages in the real sense

The format looks like this:

[image upload failed…(image-d5e4C6-1606809640424)]

A broadcast packet is composed of several broadcast units AD Structure. The composition of each AD Structure is: The first byte of the data part represents the Type of the data. AD Type determines what the following data represents. For the data Type represented by each value, see the official documentation. The remaining Leng-1 bytes represent the real data

02 01 06 02 indicates that the following data has two bytes. 01 indicates the data type. 0x06 = 0000 0110 Each byte has different meaningsCopy the code

1A ff 4C 00 02 15 fd A5 06 93 A4 e2 4f b1 AF CF C6 EB 07 64 78 25 27 11 4c b9 c5 1A ff 4C 00 02 15 fd A5 06 93 A4 E2 4f b1 AF CF C6 EB 07 64 78 25 27 11 4C 00 represents the ID of the company, 004C represents the identifier bit of Apple's 02 15 Beacon. Fd a5 06 93 A4 E2 4f b1 AF CF C6 EB 07 64 78 25 Beacon UUID 27 11 is the major value 4C b9 is the minor value C5 is Measured Power represents the RSSI value of the equipment at 1 meter, which is used for distance measurementCopy the code

In fact, this paragraph is mainly defined by Apple on the basis of the Bluetooth protocol.

If 1AFF4C000215 is matched, the device is an iBeacon device

Bluetooth reply packet

04 3E 38 0D 01 1B 00 01 8B 03 00 B0 01 C2 01 00 FF 7F AF 00 00 00 00 00 00 00 00 00 00 00 00 1E 29 bytes 02 0A 00 08 16 F0 FF 64 27 11 4c b9 11 09 4D 69 6E 69 42 65 61 63 6f 6E 5f 30 30 39 30 37 30 bytes 02 0A 00 02 Indicates the following data length of 2 bytes. 0A indicates the data type Tx Power Level The value ranges from -127 to 127 dBm. 00 indicates 0 dBm 4C b9 08 indicates the Data length. 16 Indicates Service Data. Service Data consists of the Service UUID and Service Data Data 11 09 4D 69 6E 69 42 65 61 63 6F 6E 11 Indicates the data length. 09 indicates the complete name of the device. 4D 69 6E 69 42 65 61 63 6F 6E is the classic code of the device name MiniBeacon M I N I B E A C O N 5F 30 30 39 30 37 these data are randomly added by the developers of Beacon and do not conform to the content of the agreementCopy the code

The broadcast package received in Android

Above, we analyzed broadcast packets and reply packets in bluetooth original packets respectively. In fact, for iBeacon, most of the contents in broadcast packets were determined, only UUID Major Minor would change. And the role each position represents has been defined by Apple. If you want more content in the packets sent by iBeacon, you can work with the reply packets, which are 32 bytes long. We just need to add data to the reply packet as per the protocol.

For an Android client, the broadcast packet obtained by scanresult.getscanRecord ().getBytes() is 62 bytes, which extracts the contents of the original packet from above, preserving only the second line. This is the second line of the Bluetooth broadcast packet (30 bytes) + the second line of the Bluetooth reply packet (up to 32 bytes), supplemented with 0 if there are not enough bits.

So we can now parse the broadcast package pretty well based on the obtained byte[] array.

Byte [] result = scanresult.getscanRecord ().getbytes (); // UUID contains result[9] and result[24] result[9]-- result[24]; // Major result[25] result[26] // Minor result[27] result[28] // Measured Power result[29] // Generally we will directly convert the broadcast package to 16 String uuid = broadcast. subString (18, 50); // As for the content of the reply packet, it will be analyzed according to the specific format of the broadcast packet. For example, your hardware developers put the battery in the packet, so you can agree where to put it, and then you can directly fetch it.Copy the code

About methods in ScanResult

None of these methods are parsed directly from the broadcast received from Android (scanresult.getscanRecord ().getBytes()), but rather from the raw packet.

GetTxPower gets transmitted power, if this iBeacon does not support it, then the result is 127

The latter several methods are not effective, the key depends on whether the device supports

The key way to

These methods in ScanRecord are important because they relate to the broadcast packages we receive.

For example, if the TxPowerLevel is set in the reply packet, we can get it directly by getTxPowerLevel(). For the broadcast package in the example above, you can get 0 by calling the getTxPowerLevel() method

Other methods are similar, as long as the data in your reply packet is in the correct format, it can be resolved.

For example:

For example, the broadcast package received by Android is:

0201061 aff4c0002150123456789abcdef0123456789abcdef00000007c5 020 a00:1450:8006 0303 f1ff 0 e16f1ff6400000007ac233f66c401 broadcast packets 070965526 f7574650000 response packetCopy the code

GetTxPowerLevel () returns 0 because there is correctly formatted data 020A00 in the reply packet

GetServiceData () will return value, because there is a corresponding data in the response packet 0 e16f1ff6400000007ac233f66c401

0E indicates the Data length. 16 indicates the type. Service data-16-bit UUID (not only UUID but also Data) The first two bytes indicate the UUID 6400000007AC233F66C401 Map<ParcelUuid byte[]> getServiceData() returns the value of the UUID and data as key-value pairs. The remaining bits of the changed UUID do not change. If the UUID in the broadcast packet is not F1FF, ParcelUuid = ParcelUuid. FromString (" 0000FFf1-0000-1000-8000-00805f9b34Fb "); Byte [] is the byte value corresponding to the data partCopy the code

The List getServiceUuids() method corresponds to the data 0303F1FF in the reply packet. FromString (” 0000FFF1-0000-1000-8000-00805f9b34fb “); fromString(” 0000ffF1-0000-1000-8000-00805f9b34fb “);

The following methods are also used to parse data from 62 byte broadcast packets received by Android

String getDeviceName() gets the name required to broadcast the packet with the corresponding data 070965526F7574650000

SpareArray < byte [] > getManufacturerSpecificaData () to get the manufacturer’s data, corresponding to the four c000215

Byte [] getManufacturerSpecificData (int) manufacture according to the manufacturer code byte (4 c corresponding decimal)

Data types correspond to tables