Android 蓝牙4.0BLE连接
GATT全称Generic Attribute Profile,中文名叫通用属性协议,它定义了services和characteristic两种东西来完成低功耗蓝牙设备之间的数据传输。它是建立在通用数据协议Attribute Protocol (ATT),之上的,ATT把services和characteristic以及相关的数据保存在一张简单的查找表中,该表使用16-bit的id作为索引。
一旦两个设备建立了连接,GATT就开始发挥作用,同时意味着GAP协议管理的广播过程结束了。但是必须要知道的是,建立GATT连接必要经过GAP协议。
最重要的事情,GATT连接是独占的,也就意味着一个BLE周边设备同时只能与一个中心设备连接。一旦周边设备与中心设备连接成功,直至连接断开,它不再对外广播自己的存在,其他的设备就无法发现该周边设备的存在了。
周边设备和中心设备要完成双方的通信只能通过建立GATT连接的方式。
1.png
一个ble蓝牙设备有多个包括多个Profile
一个Profile中有多个服务Service(通过服务的uuid找到对应的Service)
一个Service中有多个特征Characteristic(通过特征的uuid找到对应的Characteristic)
一个Characteristic中包括一个value和多个Descriptor(通过Descriptor的uuid找到对应的Descriptor)
其次 要知道一些名词:
1、profile
profile可以理解为一种规范,一个标准的通信协议,它存在于从机中。蓝牙组织规定了一些标准的profile,例如 HID OVER GATT ,防丢器 ,心率计等。每个profile中会包含多个service,每个service代表从机的一种能力。
2、service
service可以理解为一个服务,在ble从机中,通过有多个服务,例如电量信息服务、系统信息服务等,每个service中又包含多个characteristic特征值。每个具体的characteristic特征值才是ble通信的主题。比如当前的电量是80%,所以会通过电量的characteristic特征值存在从机的profile里,这样主机就可以通过这个characteristic来读取80%这个数据
3、characteristic
characteristic特征值,ble主从机的通信均是通过characteristic来实现,可以理解为一个标签,通过这个标签可以获取或者写入想要的内容。
4、UUID
UUID,统一识别码,我们刚才提到的service和characteristic,都需要一个唯一的uuid来标识
UUID的格式:00001101-0000-1000-8000-00805F9B34FB
整理一下,每个从机都会有一个叫做profile的东西存在,不管是上面的自定义的simpleprofile,还是标准的防丢器profile,他们都是由一些列service组成,然后每个service又包含了多个characteristic,主机和从机之间的通信,均是通过characteristic来实现。
链接:https://www.jianshu.com/p/3711cfbf7128
如果拿到一个BLE设备,不知道服务ID,不知道读写的特征值characteristic,可以通过
List<BluetoothGattService> services = gatt.getServices();来查看所有的服务,和该服务下的特征值.打印出来.
image.png
可以通过下载LightBlue(前往iPhone APPstore下载),然后连接BLE设备,就可以查看哪个服务是有关读写服务的,还有其对应的读写特征值是多少.
434694710209421345.jpg
BluetoothGattCallback
//ble蓝牙服务的回调,连接状态改变,发现服务
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
//收到设备notify值 (设备上报值),根据 characteristic.getUUID()来判断是谁发送值给你,根据characteristic.getValue()来获取这个值
}
//如果读取电量(或者读取其他值)成功之后 ,会来到 回调:
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
//读取到值
//收到设备notify值 (设备上报值)
}
//如果下发配置成功之后,会来到回调:
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
//write成功(发送值成功)
}
}
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (status == BluetoothGatt.GATT_SUCCESS) {
if (newState == BluetoothGatt.STATE_CONNECTED) {
// 连接成功
Timber.i("Connected to GATT server.");
//连接成功之后,我们应该立刻去寻找服务(上面提到的BluetoothGattService),只有寻找到服务之后,才可以和设备进行通信.
mBluetoothGatt.discoverServices();
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
// 断开连接
}
}
}
@Override
public void onDescriptorRead(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
//标志读取成功
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
//获取到RSSI, RSSI 正常情况下 是 一个 负值,如 -33 ; 这个值的绝对值越小,代表设备离手机越近
//通过mBluetoothGatt.readRemoteRssi();来获取
}
}
@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
super.onReliableWriteCompleted(gatt, status);
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
//寻找到服务
//根据得到的服务ID,用gatt.getService(uuid)去拿到读写服务
BluetoothGattService serviceRead = gatt.getService(UUID.fromString(GattAttributes.BLE_SPP_SERVICE_READ));
BluetoothGattService serviceWrite = gatt.getService(UUID.fromString(GattAttributes.BLE_SPP_SERVICE_WRITE));
if (serviceWrite != null) {
//找到服务,继续查找特征值,拿到写给设备的特征
BluetoothGattCharacteristic mWriteCharacteristic = serviceWrite.getCharacteristic(UUID.fromString(GattAttributes.BLE_SPP_WRITE_CHARACTERISTIC));
}
//拿到设备主动上报信息的特征
BluetoothGattCharacteristic mNotifyCharacteristic = serviceRead.getCharacteristic(UUID.fromString(GattAttributes.BLE_SPP_NOTIFY_CHARACTERISTIC));
if (mNotifyCharacteristic != null) {
//使能Notify,这句话是设置给BLE设备,让设备能够主动上报信息
setCharacteristicNotification(mNotifyCharacteristic, true);
}
if (bluetoothLeService.mBluetoothGatt != null) {
//将需要发送的数据byte数组,setValue设置给mWriteCharacteristic
bluetoothLeService.mWriteCharacteristic.setValue(byte[ ] b);
//发送数据的方法
boolean sendSuccess = bluetoothLeService.mBluetoothGatt.writeCharacteristic(bluetoothLeService.mWriteCharacteristic);
}
}
}
};