Android BLE Development Guide II: Broadcast Data Analysis

broadcast data structure

When the BLE peripheral starts to work, it will send out a broadcast for the central device to discover. The broadcast data packet contains the relevant information of the peripheral, such as the MAC address of the device, the name, the UUID of the Service list, and so on.

The data structure of the broadcast packet is fixed and stipulated in accordance with the relevant Bluetooth specifications.
Each packet is 31 bytes, and the data packet is divided into two parts: valid data (significant) and invalid data (non-significant).

Valid data part: Contains several broadcast data units AD Structure. As shown in the figure, the composition of AD Structure is: the first byte is the length value Len, indicating that the next Len bytes are the data part. The first byte of the data part indicates the data type AD Type , and the remaining Len - 1 byte is the real data AD data. Among them, AD type is very critical, which determines what the data of AD Data represents and how to analyze it.

Invalid data part: Because the length of the broadcast packet must be 31 bytes, if the valid data part is less than 31 bytes, the rest will be filled with 0. This part of the data is invalid, and can be ignored when explaining.
ble_ad_structure

AD Type type

AD Type includes the following types:

Flags: TYPE = 0x01 This data is used to identify the function of the physical connection of the device LE. DATA is a Flag value of 0 to multiple bytes, and each bit is 0 or 1 to indicate whether it is True. This data must be included if any of the bits are not 0 and the advertisement packet is connectable. The definition of each bit is as follows:

bit 0: LE 有限发现模式
bit 1: LE 普通发现模式
bit 2: 不支持 BR/EDR
bit 3: 对 Same Device Capable(Controller) 同时支持 BLE 和 BR/EDR
bit 4: 对 Same Device Capable(Host) 同时支持 BLE 和 BR/EDR
bit 5..7: 预留

The Service UUID broadcast data generally broadcasts the GATT Service supported by the device to tell the outside the Service supported by the device. There are three types of UUID: 16 bit, 32bit, 128 bit. In broadcasting, each type has two categories: complete and non-complete. In this way, there are 6 AD Types in total.

非完整的 16 bit UUID 列表: TYPE = 0x02;
完整的 16 bit UUID 列表: TYPE = 0x03;
非完整的 32 bit UUID 列表: TYPE = 0x04;
完整的 32 bit UUID 列表: TYPE = 0x05;
非完整的 128 bit UUID 列表: TYPE = 0x06;
完整的 128 bit UUID 列表: TYPE = 0x07;

Local Name device name DATA is a string of names. Local Name can be the full name of the device, or an abbreviation of the device name, where the abbreviation must be several characters in front of the full name.

设备全名: TYPE = 0x08
设备简称: TYPE = 0x09

TX Power Level: TYPE = 0x0A indicates the signal strength of the broadcast packet sent by the device. The DATA section is a byte representing -127 to +127 dBm.

Security Manager Out of Band: TYPE = 0x11 : DATA is also a Flag, and each bit represents a function:

bit 0: OOB Flag,0 表示没有 OOB 数据,1 表示有
bit 1: 支持 LE
bit 2: 对 Same Device Capable(Host) 同时支持 BLE 和 BR/EDR
bit 3: 地址类型,0 表示公开地址,1 表示随机地址

Peripheral (Slave) connection interval range: TYPE = 0x12 : The maximum and minimum connection interval of Slave is defined in the data, and the data contains 4 bytes:

前 2 字节:定义最小连接间隔,取值范围:0x0006 ~ 0x0C80,而 0xFFFF 表示未定义;
后 2 字节:定义最大连接间隔,同上,不过需要保证最大连接间隔大于或者等于最小连接间隔。

Service Search : Peripheral devices can ask the central device to provide corresponding services. Its data definition is similar to the previous Service UUID:

16 bit UUID 列表: TYPE = 0x14
32 bit UUID 列表: TYPE = 0x??
128 bit UUID 列表: TYPE = 0x15

Service Data : The data corresponding to the Service.

16 bit UUID Service: TYPE = 0x16, 前 2 字节是 UUID,后面是 Service 的数据;
32 bit UUID Service: TYPE = 0x??, 前 4 字节是 UUID,后面是 Service 的数据;
128 bit UUID Service: TYPE = 0x??, 前 16 字节是 UUID,后面是 Service 的数据;

Public target address : TYPE = 0x17, indicating that the broadcast packet is expected to be processed by the specified target device. This device is bound to the public address. DATA is the target address list, each address is 6 bytes.

Random target address : TYPE = 0x18, the definition is similar to the previous one, it means that the broadcast packet is expected to be processed by the specified target device, this device is bound with a random address, DATA is the target address list, each address is 6 bytes.

Appearance : TYPE = 0x19, DATA indicates the appearance of the device.

Manufacturer-defined data: TYPE = 0xFF : In the manufacturer-defined data, the first two bytes represent the manufacturer ID, and the rest are added by the manufacturer according to requirements, and the data content inside is defined by itself.

Some common data are listed here, and there are some other data.

Broadcast data analysis

In Android, there are two sets of APIs for scanning Bluetooth devices, one is on Android 4.3, and the scanned broadcast data needs to be parsed by itself; the other is on Android 5.0, and the system will analyze the scanned broadcast data for us .
The following is the open scan code on Android4.3:

	//扫描结果回调
    val leScanCallback = object : BluetoothAdapter.LeScanCallback {
    
    
        override fun onLeScan(device: BluetoothDevice, rssi: Int, scanRecord: ByteArray) {
    
    
			//回调在子线程
			ParseBluetoothAdData.parse(scanRecord)//解析广播数据
        }
    }
	val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
	if (bluetoothAdapter.isEnabled) {
    
    //蓝牙为打开状态
	    bluetoothAdapter.startLeScan(leScanCallback)//开始扫描,传入回调接口
	}

The following is the code for parsing the broadcast, here only UUID, manufacturer data and device name are parsed:

object ParseBluetoothAdData {
    
    
    fun parse(bytes: ByteArray): AdData {
    
    
        val baseUuid = "%08X-0000-1000-8000-00805F9B34FB"
        val uuidS = ArrayList<UUID>()
        var manufacturerByte: ByteArray? = null
        var name: String? = null
        val buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN)
        while (buffer.remaining() > 2) {
    
    
            var length = buffer.get().toInt() and 0xff
            if (length == 0) {
    
    
                break
            }
            val type = buffer.get().toInt() and 0xff
            length--
            when (type) {
    
    
                0x01 -> {
    
    
                    buffer.position(buffer.position() + length)
                }
                0x02, 0x03, 0x14 -> {
    
    
                    while (length >= 2) {
    
    
                        uuidS.add(UUID.fromString(String.format(baseUuid, buffer.short)))
                        length -= 2
                    }
                }
                0x04, 0x05 -> {
    
    
                    while (length >= 4) {
    
    
                        uuidS.add(UUID.fromString(String.format(baseUuid, buffer.int)))
                        length -= 4
                    }
                }
                0x06, 0x07, 0x15 -> {
    
    
                    while (length >= 16) {
    
    
                        val lsb = buffer.long
                        val msb = buffer.long
                        uuidS.add(UUID(msb, lsb))
                        length -= 16
                    }
                }
                0xff -> {
    
    //厂商自定义数据
                    manufacturerByte = ByteArray(length)
                    buffer.get(manufacturerByte, 0, length)
                }
                0x09, 0x08 -> {
    
    //全名,简短名
                    val byteArray = ByteArray(length)
                    buffer.get(byteArray)
                    name = String(byteArray)
                }
                else -> {
    
    
                    buffer.position(buffer.position() + length)
                }
            }
        }
        return AdData(uuidS, manufacturerByte, name)
    }

    class AdData(val UUIDs: ArrayList<UUID>, val manufacturerByte: ByteArray?, val name: String?)
}

The above content is excerpted from

BLE broadcast data analysis

Guess you like

Origin blog.csdn.net/ganduwei/article/details/95236917